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;
}
發佈了116 篇原創文章 · 獲贊 48 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章