ZOJ 3620 Escape Time II【dfs】

题目链接

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;
}

你可能感兴趣的:(ACM,DFS)