【 OJ 】 HDOJ1044 18年12月3日19:00 [ 38 ]
阿新 • • 發佈:2018-12-23
本題基本思路大致相同,先用BFS算出所有節點對的最短距離,然後用DFS遞迴所有情況得出最大結果(合理剪枝)
思路還是很簡單的,但是很遺憾此題沒有被AC,WA了,不清楚哪裡錯了...估計啥格式啥的...細節吧....
程式碼僅供參考吧...ummm
# include<iostream> #include<queue> # define NMAX 1000001 using namespace std; struct Point { int x, y, step; bool check(int X, int Y) { if ((x >= 0 && x < X) && (0 <= y&&y < Y)) return true; return false; } }; char Map[50][50]; bool MapVisit[50][50];//用於判斷點是否被訪問 Point P[12];//記錄12個位置 10個珠寶+S+End(起點終點) int dir[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//東南西北 int M_[12][12];//記錄12點之間的最短路徑 bool JewelVisit[12];//訪問表 0 起點 1 終點 int V[12] = { 0,0 };//珠寶價值 0 起點 1 終點 int T, L, W, H, M;//執行次數 列 行 限制時間 珠寶 int Stack[12], Stack_index;//用於記錄DFS探索的最多寶物 bool Flag;//用於判斷是否結束DFS void BFS(void) { queue<Point>q; Point p, tp; int i, j, k; for (i = 0; i < M + 2; i++) { memset(MapVisit, 0, sizeof(MapVisit));//初始化地圖訪問表 while (!q.empty())q.pop();//初始化佇列 if (i == 1)continue;//終點沒必要計算 q.push(P[i]);//起點入隊 while (!q.empty()) { tp = p = q.front();//取對頭元素 q.pop();//出隊 for (k = 0; k < 4; k++, tp = p) {//四向檢查 tp.x += dir[k][0]; tp.y += dir[k][1];//向 dir【i】移動 if (tp.check(H, W)) {//合法可走 if (Map[tp.x][tp.y] != '*' && !MapVisit[tp.x][tp.y]) { tp.step++; q.push(tp); MapVisit[tp.x][tp.y] = true; if ('A' <= Map[tp.x][tp.y] && Map[tp.x][tp.y] <= 'Z') {//遇到了珠寶 int temp = Map[tp.x][tp.y] - 'A' + 2; M_[i][temp] = tp.step;//記錄當前BFS的第 i 個珠寶到探索到的第 temp 個珠寶最短路徑 } if (Map[tp.x][tp.y] == '<') M_[i][1] = tp.step;//0 起點 1 終點 } } } } }//初始化所有珠寶之間的最短距離 } void DFS(int Curent_Jewel, int Curent_Limit) { if (!JewelVisit[0]) { JewelVisit[0] = true; Stack[Stack_index++] = 0;// 0 起點 1 終點 2-12 代表寶物 ABC..... } for (int i = M + 1; i >0; i--) {//從第 12 個寶物開始探索直到終點 if (JewelVisit[i])continue;//該寶物被探索就下一個 if (M_[Curent_Jewel][i] <= Curent_Limit) {//剩餘時間還能到達第 i 個寶物 if (i == 1) { Flag = true;//找到了最大路徑 return; } if (M_[i][1] < Curent_Limit - M_[Curent_Jewel][i])continue;//去拿了此寶物,但是到達終點的時間是不夠的 Stack[Stack_index++] = i;//第 i 個寶物入棧 JewelVisit[i] = true; DFS(i, Curent_Limit - M_[Curent_Jewel][i]);//現在當前寶物變成 i 剩餘時間為當前剩餘時間減去當前寶物到 i寶物的時間開銷 if (Flag)return;//已經找到最大值 Stack_index--; JewelVisit[i] = false; } } } int main(void) { cin >> T; int time = 0; int Total_V; while (T--) { int i, j; //初始化區域 //---------------------------------------- memset(JewelVisit, 0, sizeof(JewelVisit)); Stack_index = 0;//初始化Stack_index Flag = false;//初始化Flag for (i = 0; i < 12; ++i) for (j = 0; j < 12; j++) M_[i][j] = NMAX;//初始化M_表 //----------------------------------------- cin >> W >> H >> L >> M;//錄入基本資訊 for (i = 2; i < M + 2; i++) { cin >> V[i]; }//錄入珠寶價值 for (i = 0; i < H; i++) { for (j = 0; j < W; j++) { cin >> Map[i][j]; if ('A' <= Map[i][j] && Map[i][j] <= 'Z') { int k = Map[i][j] - 'A' + 2; P[k].step = 0; P[k].x = i; P[k].y = j; } if (Map[i][j] == '@') { P[0].x = i; P[0].y = j; P[0].step = 0; }//錄入起點資訊 if (Map[i][j] == '<') { P[1].x = i; P[1].y = j; P[1].step = 0; }//錄入終點資訊 } }//錄入地圖資訊 BFS();//廣搜出所有結點對最短距離 DFS(0, L);//深搜出最大結果 Total_V = 0; for (i = 0; i < Stack_index; i++) { Total_V += V[Stack[i]]; } if (M_[0][1] > L) cout << "Impossible" << endl; else cout << "Case " << ++time << ":" << endl << "The best score is " << Total_V << "." << endl; if (T) cout << endl; } system("pause"); return 0; }