Travel(HDU 4284状压dp)

题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走,一个城市只能工作一次,问pp是否能游览n个城市回到城市1.

分析:这个题想到杀怪(Survival(ZOJ 2297状压dp)

那个题,也是钱如果小于0就挂了,最后求剩余的最大钱数,先求出最短路和

Hie with the Pie(POJ 3311状压dp)

送披萨那个题相似。

#include <map>

#include <set>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <cstdio>

#include <vector>

#include <string>

#include <cctype>

#include <complex>

#include <cassert>

#include <utility>

#include <cstring>

#include <cstdlib>

#include <iostream>

#include <algorithm>

using namespace std;

typedef pair<int,int> PII;

typedef long long ll;

#define lson l,m,rt<<1

#define pi acos(-1.0)

#define rson m+1,r,rt<<11

#define All 1,N,1

#define read freopen("in.txt", "r", stdin)

#define N 1<<16

#define INF 99999999

const int mod =  1000000007;

int n,m,money,tn;

int dp[N][20],cost[120][120];

struct city{

    int in,c,d;

}t[20];

void floyd(){

    for(int k=1;k<=tn;++k)

        for(int i=1;i<=tn;++i)

        for(int j=1;j<=tn;++j)

    cost[i][j]=min(cost[i][j],cost[i][k]+cost[k][j]);

}

void solve(){

    int cas=(1<<n)-1;

    for(int i=0;i<=cas;++i)

     for(int j=0;j<n;++j)

        dp[i][j]=-INF;

    for(int i=0;i<n;++i)

        if(money>=cost[1][t[i].in]+t[i].d)

        dp[1<<i][i]=money-cost[1][t[i].in]-t[i].d+t[i].c;

    for(int i=1;i<=cas;++i)

    for(int j=0;j<n;++j){

        if(dp[i][j]==-INF||!(i&(1<<j)))continue;

        for(int k=0;k<n;++k){

            if(j==k)continue;

            int  c=cost[t[j].in][t[k].in]+t[k].d;

        if(!(i&(1<<k))&&dp[i][j]>=c){

            int tot=dp[i][j]-c+t[k].c;

            dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],tot);

        }

        }

    }

    int f=0;

    for(int i=0;i<n;++i)

    if(dp[cas][i]>=cost[1][t[i].in]){

       // cout<<dp[cas][i]<<endl;

        f=1;

        break;

    }

    if(f)printf("YES\n");

    else printf("NO\n");

}

int main()

{

    int te;

    scanf("%d",&te);

    while(te--){

        scanf("%d%d%d",&tn,&m,&money);

        for(int i=0;i<=tn;++i)

            for(int j=0;j<=tn;++j)

        {

            if(i==j)cost[i][j]=0;

            else cost[i][j]=INF;

        }

        int u,v,c;

        for(int i=0;i<m;++i){

            scanf("%d%d%d",&u,&v,&c);

            cost[u][v]=cost[v][u]=min(cost[u][v],c);

        }

        floyd();

        scanf("%d",&n);

        for(int i=0;i<n;++i)

            scanf("%d%d%d",&t[i].in,&t[i].c,&t[i].d);

        solve();

    }

return 0;

}

  

你可能感兴趣的:(HDU)