这很显然是一道搜索题,用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;
}