hdu 4284 状态压缩

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4284

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int maxn = 105;
const int maxm = 16;
const int INF = 0x3f3f3f3f;

int dp[maxm][1<<maxm];   //dp[i][S],当前在i,访问完S中的点还剩的最大money数。最后判断是不是大于等于0.
int dist[maxn][maxn];    //dist[i][j] 表示从i到j,所需的最小花费。
int N,M,Money,H;
int C[maxm],D[maxm];
int Must[maxm];

int main()
{
    //freopen("E:\acm\input.txt","r",stdin);
    int T;
    cin>>T;
    while(T--){
        cin>>N>>M>>Money;

        for(int i=0;i<=N;i++)
            for(int j=0;j<=N;j++)
                dist[i][j] = INF;
        for(int i=1;i<=N;i++)   dist[i][i] = 0;
        for(int i=1;i<=M;i++){
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            if(dist[u][v] > w)
                dist[u][v] = dist[v][u] = w;  //这个地方没考虑。
        }

        cin>>H;
        for(int i=0;i<H;i++)
            scanf("%d %d %d",&Must[i],&C[i],&D[i]);

        for(int k=1;k<=N;k++)
            for(int i=1;i<=N;i++)
                if(dist[i][k] < INF){
                    for(int j=1;j<=N;j++){
                        if(dist[k][j] < INF){
                            dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);
                        }
                    }
                }

        memset(dp,-0x3f,sizeof(dp));
        for(int i=0;i<H;i++){
            if(Money -dist[1][Must[i]]- D[i]>=0)
              dp[i][1<<i] = Money - dist[1][Must[i]] - D[i] + C[i];
        }

        int All = (1<<H) - 1;  //这个地方WA
        for(int S=0;S<=All;S++){ //理解偏差;
            for(int i=0;i<H;i++){
               if(!((1<<i)&S) || dp[i][S] < 0)  continue; 
            
                for(int j=0;j<H;j++){
                    if(((1<<j)&S) || i == j ) continue;
                    if(dp[i][S] - dist[Must[i]][Must[j]]- D[j] >= 0 ){
                        dp[j][1<<j|S] = max(dp[j][1<<j|S] , dp[i][S] - dist[Must[i]][Must[j]] - D[j] + C[j]);
                    }
                }
            }
        }

        bool flag = false;
        for(int i=0;i<H;i++){
            if(dp[i][All] - dist[Must[i]][1] >= 0){
                flag = true;    break;
            }
        }

        if(flag)  printf("YES
");
        else      printf("NO
");
    }
}
View Code
原文地址:https://www.cnblogs.com/acmdeweilai/p/3297838.html