hdu 4284(状压dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4284
思路:类似于poj3311:http://poj.org/problem?id=3311,首先floyd预处理出两点之间的最短距离,然后就是枚举所有的状态了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN 111 7 #define inf 0x3f3f3f3f 8 9 int map[MAXN][MAXN]; 10 int dp[1<<17][17]; 11 int city[17],cost[17],value[17]; 12 int N,M,H,money; 13 14 void floyd() 15 { 16 for(int k=1;k<=N;k++) 17 for(int i=1;i<=N;i++) 18 for(int j=1;j<=N;j++) 19 if(map[i][k]<inf&&map[k][j]<inf&&map[i][k]+map[k][j]<map[i][j]) 20 map[i][j]=map[i][k]+map[k][j]; 21 } 22 23 24 int main() 25 { 26 int _case,u,v,w; 27 scanf("%d",&_case); 28 while(_case--){ 29 scanf("%d%d%d",&N,&M,&money); 30 for(int i=1;i<=N;i++) 31 for(int j=1;j<=N;j++) 32 map[i][j]=(i==j)?0:inf; 33 while(M--){ 34 scanf("%d%d%d",&u,&v,&w); 35 map[u][v]=map[v][u]=min(map[u][v],w); 36 } 37 floyd(); 38 scanf("%d",&H); 39 for(int i=0;i<H;i++){ 40 scanf("%d%d%d",&city[i],&value[i],&cost[i]); 41 } 42 memset(dp,-1,sizeof(dp)); 43 for(int i=0;i<H;i++){ 44 int tmp=money-map[1][city[i]]-cost[i]; 45 if(tmp>=0)dp[(1<<i)][i]=tmp+value[i]; 46 } 47 for(int state=0;state<(1<<H);state++){ 48 for(int i=0;i<H;i++){ 49 if((state&(1<<i))==0)continue; 50 if(dp[state][i]<0)continue; 51 for(int j=0;j<H;j++){ 52 if(state&(1<<j))continue; 53 if(map[city[i]][city[j]]==inf)continue; 54 if(dp[state][i]-map[city[i]][city[j]]-cost[j]<0)continue; 55 dp[state|(1<<j)][j]=max(dp[state|(1<<j)][j],dp[state][i]-map[city[i]][city[j]]-cost[j]+value[j]); 56 } 57 } 58 } 59 bool flag=false; 60 for(int i=0;i<H;i++){ 61 if(dp[(1<<H)-1][i]-map[city[i]][1]>=0){ 62 flag=true; 63 break; 64 } 65 } 66 flag?puts("YES"):puts("NO"); 67 } 68 return 0; 69 } 70 71 72 73 74 75 76 77 78