这很显然是一道搜索题,用DFS可以很方便地解决。程序雏形很快就编出来了,可是很多细节问题没注意,结果WA了几次,T.T
做个总结,留下经验:
1.开始时我是标记顶点(就是room)而非路径,但此题是允许环的存在的,比如A — B — A,如果标记顶点的话,由A再到B就不行了。所以标记路径,从A到B时就标记路径<A,B>,做标记是为了避免重复走同一路径,为什么要避免?显然再次走<A,B>时已经不能收获jewel又要耗费时间。
2.虽然顶点不需标记,但对已经搜索过的顶点,要将其含有的jewel数清零。一开始我就没注意到这点。
3.恢复现场的工作要做好。
4.到达e不能马上停下,如果此时总时间不超过规定时间 t 的话,还可以搜索其他顶点以获得更多的jewel,但最终一定要再回到e,每次到e都要更新获取jewel的最大数量。
AC code:
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; int n, m, t, s, e; int jew[10], cost[10][10], maxjew; bool vis[10][10]; //r:room, sj:sum of jewels, st:sum of time void DFS(int r, int sj, int st) { if(r == e && sj > maxjew) maxjew = sj; for(int i = 0; i < n; i++) { if(!vis[r][i] && cost[r][i] && r != i && st + cost[r][i] <= t) { //因为往下一层递归时jew[i]要设为0,故此处保存其值以还原 int val = jew[i]; jew[i] = 0; //注意不是vis[r][i]=vis[i][r]=1,因为路径可以构成环,比如A-B-A,如果 //从A到B的同时标记B到A的路径,就可能造成搜索B后到不了e(如必须到经A到e) vis[r][i] = 1; DFS(i, sj + val, st + cost[r][i]); vis[r][i] = 0; jew[i] = val; } } return ; } int main() { while(scanf("%d %d %d", &n, &m, &t) != EOF) { //初始化 memset(cost, 0, sizeof(cost)); memset(vis, 0, sizeof(vis)); maxjew = 0; //输入 scanf("%d %d", &s, &e); for(int i = 0; i < n; i++) scanf("%d", &jew[i]); for(int j = 0, a, b; j < m ;j++) { scanf("%d %d", &a, &b); scanf("%d", &cost[a][b]); cost[b][a] = cost[a][b]; } //dfs int val = jew[s]; jew[s] = 0; //s处的jewel一开始就被拿走 DFS(s, val, 0); //输出 printf("%d\n", maxjew); } return 0; }