題目鏈接
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;
}