日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hdu1010 Tempter of the Bone

發布時間:2024/4/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu1010 Tempter of the Bone 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 轉載自:http://acm.hdu.edu.cn/forum/read.php?tid=6158
  • sample input:
  • 4 4 5
  • S.X.
  • ..X.
  • ..XD
  • ....
  • 問題:
  • (1):
  • 在發現當前節點無法到達時,這點彈出棧,并且把這點的標記重新刷為'.'
  • (2):
  • 如何在dfs中既要保證到達又要使時間正好呢?? 在函數中通過這種形式實現:
  • dfs(int si,int sj,int cnt) 就是用cnt來記錄當時的時間,并且在
  • if( si==di && sj==dj && cnt==t )
  • ? ? {
  • ? ? ? ? escape = 1;
  • ? ? ? ? return;
  • ? ? }
  • 的時候 即當前點到達了終點并且時間恰好等于題目所給限制時間時,跳出
  • 并且escape標記為真
  • (3):
  • 如何讓一個點有順序地遍歷它四周地能到達的點呢??
  • 聰明并且簡短的方法是設施一個dir[4][2] 數組 控制方向
  • 并且設置它的值為dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};
  • 遍歷的時候用for(i:0->4)就非常方便了
  • (4):
  • 千萬要注意的是節點越界的情況, dfs(int si,int sj,int cnt)的時候一定要把 si, sj 控制在給你的矩陣內 在后面會提到一個我的列子 就是因為訪問了[0, -1]的位置導致了其
  • 他數據被更改
  • (5):
  • 讀入矩陣的時候,可以采用for(i = 1; i <= N; i++)
  • ? ? ? ? ? ?? ? for(j = 1; j <= M; j++)
  • ? ? ? ? ? ? ? ? scanf("%c", &map[i][j]);? ? ? ?
  • 的方法,好處在于可以控制和計算每一個讀入的數據,壞處是調試的時候對矩陣的觀察不太方便,而且好像還會有錯誤,在2102"A計劃"用這種方法讀入數據時好像就會wa,
  • 另一種方法是for(i = 0; i < N; i++) gets(map[i]);
  • 這樣讀入的數據在調試觀察的時候十分方便 gets()讀入的默認為字符串,在vc調試的時候是顯式的 可以直接觀察矩陣 缺點是對矩陣中各個數據的計算和控制無法實現,需要讀完后再遍歷一遍
  • (6)
  • 能用bfs還是盡量用bfs 我不會bfs.... dfs的遞歸在調試的時候不是很方便,而且bfs要比dfs快,調試也要方便,因為它沒有遞歸
  • (7)
  • 關于剪枝,沒有剪枝的搜索不太可能,這題老劉上課的時候講過兩個剪枝,一個是奇偶剪枝,一個是路徑剪枝
  • 奇偶剪枝:
  • 把矩陣標記成如下形式:
  • 0,1,0,1,0
  • 1,0,1,0,1
  • 0,1,0,1,0
  • 1,0,1,0,1
  • 很明顯,如果起點在0 而終點在1 那顯然 要經過奇數步才能從起點走到終點,依次類推,奇偶相同的偶數步,奇偶不同的奇數步
  • 在讀入數據的時候就可以判斷,并且做剪枝,當然做的時候并不要求把整個矩陣0,1刷一遍,讀入的時候起點記為(Si,Sj) 終點記為(Di,Dj) 判斷(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了
  • 路徑剪枝:
  • 矩陣的大小是N*M 墻的數量記為wall 如果能走的路的數量 N*M - wall 小于時間T,就是說走完也不能到總的時間的,這顯然是錯誤的,可以直接跳出了
  • 課件里面給過這題的標程,在dfs的過程中有個沒提到的剪枝,就是記錄當前點到終點的最短路,如果小于剩余的時間的話,就跳出
  • 這個剪枝我覺得更科學,它畢竟是動態的么,標程里面是這么寫的:
  • temp = (t-cnt) - abs(si-di) - abs(sj-dj);
  • if( temp<0 || temp&1 ) return;
  • 其中求當前點到終點的最短路是這樣 abs(si-di) - abs(sj-dj) 這個就比較粗糙了 明顯沒有考慮到碰到墻要拐彎的情況
  • 那求最短路有沒有什么好辦法呢?
  • 我曾經想到過用 Dijkstraq求最短路的 ,明顯大才小用,在論壇里看到一個方法覺得可以用在這里
  • 給定下例:
  • S.X.
  • ..X.
  • ..XD
  • ....
  • 每個點到終點的最短路是不是這樣呢:
  • S6X2
  • 65X1
  • 54XD
  • 4321
  • 這怎么求呢??從終點開始遍歷整個數組,終點是0,它周圍的點都+1,墻就不計數,依次類推,就能求得這個矩陣的一個最短時間矩陣,在dfs的時候比較當前點到終點的最短路,如果大于剩余時間的話就跳出
  • 這個方法的預處理還是非常快的,我沒有用過,但是感覺會非常有用處.
  • (8)
  • 在做這題的時候,我碰到過一個神奇的事情,在程序運行至下面代碼時
  • if( map[ si+dir[i][0] ][ sj+dir[i][1] ] != 'X')? ? ? ? ? ?
  • ? ? map[ si+dir[i][0] ][ sj+dir[i][1] ] = 'X';
  • T被改變了!! 這絲毫和T沒有關系啊,怎么改變T的值呢??
  • 原來在起點map[0][0]進入時,我沒有注意到map[ si+dir[i][0] ][ sj+dir[i][1] ] 實際做的是map[0][-1] = 'X'; 很危險的一個賦值,書本上千萬次強調的東西讓我碰上了,這個地方我找了很久,因此我覺得有必要單獨列出來提醒自己
  • //
  • 下面我把一個帶注釋的標程貼一下,不是我寫的注釋
  • //zju 2110 Tempter of the Bone
  • #include <stdio.h>
  • #include <iostream>
  • #include <string.h>
  • #include <stdlib.h>
  • using namespace std;
  • //迷宮地圖
  • //X: 墻壁,小狗不能進入
  • //S: 小狗所處的位置
  • //D: 迷宮的門
  • //. : 空的方格
  • char map[9][9];
  • int n,m,t,di,dj; //(di,dj):門的位置
  • bool escape;
  • int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; //分別表示下、上、左、右四個方向
  • void dfs(int si,int sj,int cnt)? //表示起始位置為(si,sj),要求在第cnt秒達到門的位置
  • {
  • ? ? int i,temp;
  • ? ? if( si>n || sj>m || si<=0 || sj<=0 ) return;
  • ? ?
  • ? ? if( si==di && sj==dj && cnt==t )
  • ? ? {
  • ? ? ? ? escape = 1;
  • ? ? ? ? return;
  • ? ? }
  • ? ?
  • ? ? //abs(x-ex) + abs(y - ey)表示現在所在的格子到目標格子的距離(不能走對角線)
  • ? ? //t-cnt是實際還需要的步數,將他們做差
  • ? ? //如果temp < 0或者temp為奇數,那就不可能到達!
  • ? ? temp = (t-cnt) - abs(si-di) - abs(sj-dj);
  • ? ?
  • ? ? if( temp<0 || temp&1 ) return;
  • ? ?
  • ? ? for( i=0; i<4; i++ )
  • ? ? {
  • ? ? ? ? if( map[ si+dir[i][0] ][ sj+dir[i][1] ] != 'X')
  • ? ? ? ? {
  • ? ? ? ? ? ? map[ si+dir[i][0] ][ sj+dir[i][1] ] = 'X';
  • ? ? ? ? ? ? ? ?
  • ? ? ? ? ? ? ? ? dfs(si+dir[i][0], sj+dir[i][1], cnt+1);
  • ? ? ? ? ? ?
  • ? ? ? ? ? ? if(escape) return;
  • ? ? ? ? ? ?
  • ? ? ? ? ? ? map[ si+dir[i][0] ][ sj+dir[i][1] ] = '.';
  • ? ? ? ? }
  • ? ? }
  • ? ?
  • ? ? return;
  • }
  • int main()
  • {
  • ? ? int i,j,si,sj;
  • ? ?
  • ? ? while( cin >> n >> m >> t)
  • ? ? {
  • ? ? ? ? if( n==0 && m==0 && t==0 )
  • ? ? ? ? ? ? break;
  • ? ?
  • ? ? ? ? int wall = 0;
  • ? ? ? ? for( i=1; i<=n; i++ )
  • ? ? ? ? ? ? for( j=1; j<=m; j++ )
  • ? ? ? ? ? ? {
  • ? ? ? ? ? ? ? ? cin >> map[i][j];
  • ? ? ? ? ? ? ? ? if(map[i][j]=='S') { si=i; sj=j; }
  • ? ? ? ? ? ? ? ? else if( map[i][j]=='D' ) { di=i; dj=j; }
  • ? ? ? ? ? ? ? ? else if( map[i][j]=='X' ) wall++;
  • ? ? ? ? ? ? }
  • ? ? ? ? ? ?
  • ? ? ? ? ? ? if( n*m-wall <= t )
  • ? ? ? ? ? ? {
  • ? ? ? ? ? ? ? ? cout << "NO" << endl;
  • ? ? ? ? ? ? ? ? continue;
  • ? ? ? ? ? ? }
  • ? ? ? ? ? ?
  • ? ? ? ? ? ? escape = 0;
  • ? ? ? ? ? ? map[si][sj] = 'X';
  • ? ? ? ? ? ?
  • ? ? ? ? ? ? dfs( si, sj, 0 );
  • ? ? ? ? ? ?
  • ? ? ? ? ? ? if( escape ) cout << "YES" << endl;
  • ? ? ? ? ? ? else cout << "NO" << endl;
  • ? ? }
  • ? ?
  • ? ? return 0;
  • }
  • 轉載于:https://www.cnblogs.com/duan-to-success/p/3854988.html

    總結

    以上是生活随笔為你收集整理的hdu1010 Tempter of the Bone的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。