题目链接
http://icpc.moe/onlinejudge/showProblem.do?problemCode=3620
思路
就是给你个无向带权图,每个点也有个价值,问在时间用完前,从起点走到终点,能获得的最大价值是多少。
数据范围相当小,但这题可以走回头路,所以如何判重是个大问题。不然数据再小死循环了也没用。
有个比较难想到思路是:每条边最多走两次,而且是来回各一次。
这么想吧,走回头路的情况只有一种,就是你发现一个很有价值的支路,但这个支路无法通向终点或者通向终点的代价太大,所以你把这个支路走到底,拿完所有宝贝再回来,但你肯定不会傻乎乎的再走回去,因为宝贝已经拿光了,所以每条边最多走两次,而且是来回。
这个想通了搜索就很简单了,dfs一下即可。我看到有人用BFS甚至用状态压缩DP也过了,我就不试了有心人可以试试。
AC代码
#include <bits/stdc++.h>
using namespace std;
int g[15][15];
int j[15];
bool vis[15][15];
bool visn[15];
int n,m,t;
int s,e;
int ans=0;
void dfs(int u,int jew)
{
if(u==e)
{
ans=max(ans,jew);
}
for(int v=0 ; v<n ; ++v)
{
if(g[u][v] && !vis[u][v] && t-g[u][v]>=0)
{
t-=g[u][v];
vis[u][v]=1;
if(!visn[v])
{
visn[v]=1;
dfs(v,jew+j[v]);
visn[v]=0;
}
else
{
dfs(v,jew);
}
vis[u][v]=0;
t+=g[u][v];
}
}
}
void init()
{
memset(g,0,sizeof g);
memset(vis,0,sizeof vis);
memset(visn,0,sizeof visn);
ans=0;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&t)!=EOF)
{
init();
scanf("%d%d",&s,&e);
for(int i=0 ; i<n ; ++i)scanf("%d",&j[i]);
for(int i=0 ; i<m ; ++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
g[a][b]=g[b][a]=c;
}
visn[s]=1;
dfs(s,j[s]);
printf("%d\n",ans);
}
return 0;
}