题意:
一个人在起点,有许多物品散落在各个地方,现在给出人起点的坐标和物品的坐标,然后给出一个要求,每次最多只能拿两个物品拿完物品必须回到原点装到包里面,求最短路程的方案,答案和路径都要输出。
这题如果是超级暴力即状态和两个点都全部枚举会超时,稍微优化下,因为先去哪个都是一样的,因为都 要回到原点,这样相当于每次是从原地出发找出然后回去,所以首先枚举状态,然后枚举第一个点,这时候先转移这个点的状态,然后再枚举第二个点,当枚举的第二个点都转移完状态后,就跳出第一个点的循环。
第一次写的代码
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; #define oo 0x3f3f3f3f #define maxn 24 int dp[(1 << 25) + 1]; int pre[(1 << 25) + 1]; int dis[26][26]; struct Node { int x, y; }a[26]; int Distance(Node n1, Node n2) { return (n1.x - n2.x)*(n1.x - n2.x) + (n1.y - n2.y)*(n1.y - n2.y); } int main() { int x, y, n; scanf("%d %d", &x, &y); scanf("%d", &n); a[n].x = x; a[n].y = y; for (int i = 0; i < n; i++) scanf("%d %d", &a[i].x, &a[i].y); for (int i = 0; i <= n;i++) for (int j = i + 1; j <= n; j++) dis[i][j] = dis[j][i] = Distance(a[i], a[j]); memset(dp, 0x3f, sizeof dp); dp[0] = 0; int all = (1 << n) - 1; for (int now = 0; now <= all; now++) { if (dp[now] == oo) continue; for (int i = 0; i < n; i++) { if (now&(1 << i)) continue; int next = now | (1 << i); if (dp[next] > dp[now] + 2.0 * dis[n][i]) { dp[next] = dp[now] + 2.0 * dis[n][i]; pre[next] = now; } for (int j = i + 1; j < n; j++) { if (now&(1 << j)) continue; next = now | (1 << j) | (1 << i); if (dp[next] > dp[now] + dis[n][i] + dis[i][j] + dis[j][n]) { dp[next] = dp[now] + dis[n][i] + dis[i][j] + dis[j][n]; pre[next] = now; } } break; } } printf("%d\n", dp[all]); int res[60], top = 0; int st = all, last, temp; while (st) { last = pre[st]; temp = st^last; st = last; res[++top] = 0; int i; for (i = 0; i < n; i++) if (temp&(1 << i)) { res[++top] = i + 1; break; } for (i++; i < n; i++) if (temp&(1 << i)) { res[++top] = i + 1; break; } } res[++top] = 0; for (int i = top; i >= 1; i--) { if (i != top) printf(" "); printf("%d", res[i]); } puts(""); return 0; }
第二次写的
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<map> using namespace std; typedef long long lld; const int oo=0x3f3f3f3f; const lld OO=1LL<<61; const int Mod=1000000007; int dp[(1<<25)+1]; int pre[(1<<25)+1]; int dis[30][30]; int n,all; struct POINT { int x,y; }po[30]; void Distance() { for(int i=0;i<=n;i++) { for(int j=i+1;j<=n;j++) { dis[i][j]=dis[j][i]=(po[i].x-po[j].x)*(po[i].x-po[j].x)+(po[i].y-po[j].y)*(po[i].y-po[j].y); } dis[i][i]=0; } } void input() { scanf("%d %d",&po[0].x,&po[0].y); scanf("%d",&n); po[n].x=po[0].x;po[n].y=po[0].y; for(int i=0;i<n;i++) scanf("%d %d",&po[i].x,&po[i].y); } void bitmasks_dp() { memset(dp,0x3f,sizeof dp); all=(1<<n)-1; dp[0]=0;///n作为起点 for(int s=0;s<=all;s++) { if(dp[s]==oo)continue; for(int i=0;i<n;i++) { if(s&(1<<i))continue; int st=s|(1<<i); if(dp[st]>dp[s]+dis[n][i]*2) { dp[st]=dp[s]+dis[n][i]*2; pre[st]=s; } for(int j=i+1;j<n;j++) { if(s&(1<<j))continue; st=s|(1<<i)|(1<<j); if(dp[st]>dp[s]+dis[n][i]+dis[i][j]+dis[j][n]) { dp[st]=dp[s]+dis[n][i]+dis[i][j]+dis[j][n]; pre[st]=s; } } break; } } } void output_ans() { printf("%d\n",dp[all]); int ans[60],cnt=0,st=all,p,temp; while(st) { p=pre[st]; temp=st^p; ans[++cnt]=0; for(int i=n-1;i>=0;i--) { if(temp&(1<<i)) ans[++cnt]=i+1; } st=p; } ans[++cnt]=0; for(int i=cnt;i>1;i--) printf("%d ",ans[i]); printf("%d\n",ans[1]); } int main() { input(); Distance(); bitmasks_dp(); output_ans(); return 0; } /** 5 2 4 7 4 7 4 3 1 -100 0 100 6 3 1 2 3 7 8 9 */