HDU - 4284 Travel(floyd+状压dp)
Travel
PP lives in city 1, and she will start her journey from city 1. and end her journey at city 1 too.
Input The first line of input consists of one integer T which means T cases will follow.
Then follows T cases, each of which begins with three integers: the number of cities N (N <= 100) , number of roads M (M <= 5000) and her initiative money Money (Money <= 10^5) .
Then follows M lines. Each contains three integers u, v, w, which means there is a road between city u and city v and the cost is w. u and v are between 1 and N (inclusive), w <= 10^5.
Then follows a integer H (H <= 15) , which is the number of chosen cities.
Then follows H lines. Each contains three integers Num, Ci, Di, which means the i_th chosen city number and Ci, Di described above.(Ci, Di <= 10^5)
Output If PP can visit all chosen cities and get all licenses, output "YES", otherwise output "NO".
Sample Input
2 4 5 10 1 2 1 2 3 2 1 3 2 1 4 1 3 4 2 3 1 8 5 2 5 2 3 10 1 2 1 100 1 2 10000 1 2 100000 1
Sample Output
YES NO
题意:1能否经过h个点并回到1处?在经过边时花费边权,第一次到达h中任意点时先花费后点权,再收获前点权,若在次过程中无法保证非负,输出NO。
先预处理出h个点之间两两的最短路,然后状压dp求出在满足限制下的最大收益,-1输出NO。
#include<bits/stdc++.h> #define MAX 105 #define INF 0x3f3f3f3f using namespace std; typedef long long ll; int a[MAX][MAX],b[16][2]; int dp[1<<15][16]; int mp[16]; int main() { int t,n,m,mon,h,i,j,k; int x,y,z; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&mon); memset(a,INF,sizeof(a)); for(i=1;i<=n;i++){ a[i][i]=0; } for(i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); if(a[x][y]==INF){ a[x][y]=z; a[y][x]=z; } else if(z<a[x][y]){ a[x][y]=z; a[y][x]=z; } } for(k=1;k<=n;k++){ for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ a[i][j]=min(a[i][j],a[i][k]+a[k][j]); } } } scanf("%d",&h); memset(mp,0,sizeof(mp)); for(i=1;i<=h;i++){ scanf("%d%d%d",&x,&y,&z); mp[i]=x; b[i][1]=y; b[i][0]=z; } memset(dp,-1,sizeof(dp)); dp[0][1]=mon; for(i=1;i<=h;i++){ if(mon-a[1][mp[i]]-b[i][0]<0) continue; dp[1<<(i-1)][i]=mon-a[1][mp[i]]-b[i][0]+b[i][1]; } for(i=0;i<(1<<h);i++){ for(j=1;j<=h;j++){ if(!(i&(1<<(j-1)))) continue; for(k=1;k<=h;k++){ if(j==k||!(i&(1<<(k-1)))) continue; if(dp[i^(1<<(j-1))][k]<0||a[mp[k]][mp[j]]==INF) continue; if(dp[i^(1<<(j-1))][k]-a[mp[k]][mp[j]]-b[j][0]<0) continue; dp[i][j]=max(dp[i][j],dp[i^(1<<(j-1))][k]-a[mp[k]][mp[j]]-b[j][0]+b[j][1]); } } } int maxx=-1; for(i=1;i<=h;i++){ maxx=max(maxx,dp[(1<<h)-1][i]-a[1][mp[i]]); } if(maxx<0) printf("NO\n"); else printf("YES\n"); } return 0; }