本題基本思路大致相同,先用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;
}