题目大意:给一个地图,地图中有一个入口,一个出口,并散落一些珠宝,一个人从入口处开始在规定的时间内到达出口,并在这个过程中获得最大的珠宝,其中每个珠宝只能获取一次。
题目解法:首先使用BFS构建一个从珠宝位置和出口及入口位置到其他珠宝或出口或入口的最短距离的网络,然后使用DFS从入口位置搜索到出口位置能获得的最大珠宝价值。
DFS时注意两个剪枝(1)得到所有珠宝时(2)到该位置时耗去的时间比要求的时间多
#include <iostream> #include <queue> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <utility> #include <vector> #define WH 60 #define M 11 using namespace std; class StatePosistion { public: int h; int w; int t; StatePosistion(int h, int w, int t):h(h), w(w), t(t){} StatePosistion(){} ~StatePosistion(){} }; char tmap[WH][WH]; bool visited[M+1]; int jewels[M], dis[M+1][M+1], maxJewels; int w, h, L, m, sum; int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; bool isLegel(StatePosistion tm) { return tm.h>=0&&tm.h<h&&tm.w>=0&&tm.w<w&&tmap[tm.h][tm.w]!='*'; } bool isGoodSite(StatePosistion tm) { return tmap[tm.h][tm.w]=='<' || tmap[tm.h][tm.w]=='@' || (tmap[tm.h][tm.w]>='A' && tmap[tm.h][tm.w]<='J'); } int getSource(char t) { switch(t){ case '<':return m+1; case '@':return 0; default:return t-'A'+1; } } void bfs(StatePosistion stt) { queue<StatePosistion > Qu; bool used[WH][WH]; int frm=getSource(tmap[stt.h][stt.w]); StatePosistion cur; memset (used, false, sizeof(used)); Qu.push(stt); used[stt.h][stt.w] = true; while (!Qu.empty()){ cur = Qu.front(); Qu.pop(); for (int i = 0; i < 4; ++i){ StatePosistion temp(cur.h+dir[i][0], cur.w+dir[i][1], cur.t+1); if (isLegel(temp) && !used[temp.h][temp.w]){ used[temp.h][temp.w] = true; Qu.push(temp); if (isGoodSite(temp)){ int to=getSource(tmap[temp.h][temp.w]); dis[frm][to] = temp.t; } } } } } void getJewels(int curpos, int curtime, int curjewels) { for (int i = 1; i <= m+1; ++i){ if (!visited[i]){ visited[i] = true; if (i == m+1){ if (dis[curpos][i] && curtime+dis[curpos][i] <= L){ maxJewels = max(maxJewels, curjewels); } } else { if (dis[curpos][i] && curtime+dis[curpos][i] <= L){ getJewels(i, curtime+dis[curpos][i], curjewels+jewels[i-1]); } } visited[i] = false; } if (maxJewels == sum)return; } } void printDis() { for (int i = 0; i <= m+1; ++i){ for (int j = 0; j <= m+1; ++j){ printf ("%3d", dis[i][j]); } printf ("\n"); } } void init() { memset (dis, 0, sizeof(dis)); for (int i = 0; i < h; ++i){ for (int j = 0; j < w; ++j){ StatePosistion tm(i, j, 0); if (isGoodSite(tm)){ bfs(tm); } } } //printDis(); } void solve() { init(); if (dis[0][m+1]==0||dis[0][m+1]>L){ cout << "Impossible" << endl; } else { memset (visited, false, sizeof(visited)); visited[0] = true; maxJewels = 0; getJewels(0, 0, 0); cout << "The best score is " << maxJewels << "." << endl; } } int main() { int t, i; cin >> t; for (int iCase = 1; iCase <= t; ++iCase){ cin >> w >> h >> L >> m; sum = 0; for (i = 0; i < m; ++i){ cin >> jewels[i]; sum += jewels[i]; } for (i = 0; i < h; ++i){ cin >> tmap[i]; } cout << "Case " << iCase << ":" << endl; solve(); if (iCase != t)cout << endl; } return 0; }