转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:给出N个人,其中0号是裁判的位置,剩下有N-1的人提问,裁判需要去回答问题,每个人有一个val,每个裁判能拿到的val的上限为K。问题最少需要几个裁判,以及最少时间
http://acm.hdu.edu.cn/showproblem.php?pid=4281
第一问可以状态压缩DP解决,dp[i]表示状态i需要几个裁判。注~~~贪心 是错的!!!!
第二问就是多个TSP问题,dp[i][j]表示当前位置 在i,可行状态为j的最小费用,best[i]表示对于状态i的最小费用(而且是一个完整状态,裁判都回到原点),因为之前TSP中是求的可行状态,也就是每个裁判的上限不能超过K。之后就是枚举所有状态,对于一个状态,枚举他的所有子集,见代码中的位运算部分。而且两个子集中必须要包含0号结点,因为每个裁判都是从0出发的
可以看这个博客:http://blog.csdn.net/woshi250hua/article/details/7961869
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<set> #define inf 1<<28 #define M 100005 #define N 55 #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define pb(a) push_back(a) #define mem(a,b) memset(a,b,sizeof(a)) #define LL long long #define MOD 1000000007 using namespace std; struct Point{ int x,y; }p[20]; int n,m,val[20],path[20][20]; int dp[16][1<<16],state[1<<16],tot; int best[1<<16],ok[1<<16]; int dist(Point p1,Point p2){ return ceil(sqrt((double)(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y))); } void Get_dist(){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) path[i][j]=dist(p[i],p[j]); } void Init(){ for(int i=0;i<n;i++) for(int j=0;j<(1<<n);j++) dp[i][j]=inf; for(int i=0;i<(1<<n);i++) best[i]=inf; dp[0][1]=0; } int check(int state){ int sum=0; for(int i=0;i<n;i++) if(state&(1<<i)) sum+=val[i]; return sum<=m; } bool cmp(int a,int b){return a>b;} int slove(){ int dp[1<<16]; for(int i=0;i<(1<<n);i++) dp[i]=inf; dp[0]=0; for(int i=0;i<tot;i++){ for(int j=(1<<n)-1;j>=0;j--){ if(dp[j]==inf) continue; if(state[i]&j) continue; dp[state[i]+j]=min(dp[state[i]+j],dp[j]+1); } } return dp[(1<<n)-1]==inf?-1:dp[(1<<n)-1]; } int TSP(){ for(int i=0;i<(1<<n);i++){ if(ok[i]) for(int j=0;j<n;j++) if(i&(1<<j)){ best[i]=min(best[i],dp[j][i]+path[j][0]); for(int k=0;k<n;k++) if(!(i&(1<<k))) dp[k][i|(1<<k)]=min(dp[k][i|(1<<k)],dp[j][i]+path[j][k]); } } for(int i=0;i<(1<<n);i++) if(i&1) for(int j=i&(i-1);j;j=i&(j-1)) best[i]=min(best[i],best[j]+best[(i-j)|1]); return best[(1<<n)-1]; } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ tot=0; for(int i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y); for(int i=0;i<n;i++) scanf("%d",&val[i]); for(int i=0;i<(1<<n);i++) { ok[i]=check(i); if(ok[i]) state[tot++]=i; } Get_dist(); Init(); int ans1=slove(); if(ans1==-1) {printf("-1 -1\n");continue;} printf("%d %d\n",ans1,TSP()); } return 0; }