标签:
题意: 有N 个点的无向图,要去其中 h个地点做事,做事需要先办理护照,之后可以挣一定数量的钱,知道了一开始有的总钱数,和 一些城市之间
道路的花费,问可不可以在 指定的 h 个城市打完工,并回到起点 1.
链接:点我
是个好题!!!
状态转移方程dp[s][i]=max(dp[s][i],dp[s‘][j]-maps[j][i]-d[i]+c[i]);
dp[s][i]表示当在状态s的时候最后再i城市打工的最多剩余钱数。
2 4 5 10 //4个点,5个道路,10单位的钱 1 2 1 2 3 2 1 3 2 1 4 1 3 4 2 3 //3个必去的 1 8 5 //编号,消耗,赚的 2 5 2 3 10 1 2 1 100 1 2 10000 1 2 100000 1
YES NO
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define INF 99999999 7 typedef long long LL; 8 using namespace std; 9 10 const int MAX=(1<<16)+10; 11 int n,m,val,h; 12 int s[20],c[20],d[20]; 13 int dp[MAX][20],dist[110][110]; 14 15 void Init(int num){ 16 for(int i=0;i<=num;++i){ 17 for(int j=i+1;j<=num;++j)dist[i][j]=dist[j][i]=INF; 18 } 19 } 20 21 void floyd(){ 22 for(int k=1;k<=n;++k){ 23 for(int i=1;i<=n;++i){ 24 for(int j=1;j<=n;++j){ 25 dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]); 26 } 27 } 28 } 29 } 30 31 void DP(){ 32 int bit=1<<(h+1); 33 memset(dp,-1,sizeof dp); 34 dp[1][0]=val; 35 for(int i=1;i<bit;++i){ 36 for(int j=0;j<=h;++j){ 37 if(dp[i][j] == -1)continue; 38 for(int k=1;k<=h;++k){ 39 if(dp[i][j]<dist[s[j]][s[k]]+d[k])continue; 40 int p=1<<k,w=c[k]-d[k]; //可以去 41 if(i&p)continue; //已经去过 42 dp[i|p][k]=max(dp[i|p][k],dp[i][j]-dist[s[j]][s[k]]+w); 43 } 44 } 45 } 46 bool flag=false; 47 for(int i=0;i<=h;++i)if(dp[bit-1][i]-dist[s[i]][1]>=0)flag=true; //没返回过1 48 if(flag)printf("YES\n"); 49 else printf("NO\n"); 50 } 51 52 int main(){ 53 int t,u,v,w; 54 scanf("%d",&t); 55 while(t--){ 56 scanf("%d%d%d",&n,&m,&val); 57 Init(n); 58 for(int i=0;i<m;++i){ 59 scanf("%d%d%d",&u,&v,&w); 60 dist[u][v]=dist[v][u]=min(dist[u][v],w); 61 } 62 scanf("%d",&h); 63 for(int i=1;i<=h;++i){ 64 scanf("%d%d%d",&s[i],&c[i],&d[i]); 65 } 66 floyd(); 67 s[0]=1,c[0]=d[0]=0; 68 DP(); 69 } 70 return 0; 71 }
标签:
原文地址:http://www.cnblogs.com/cnblogs321114287/p/4347814.html