题意:
一个人在起点,有许多物品散落在各个地方,现在给出人起点的坐标和物品的坐标,然后给出一个要求,每次最多只能拿两个物品拿完物品必须回到原点装到包里面,求最短路程的方案,答案和路径都要输出。
这题如果是超级暴力即状态和两个点都全部枚举会超时,稍微优化下,因为先去哪个都是一样的,因为都 要回到原点,这样相当于每次是从原地出发找出然后回去,所以首先枚举状态,然后枚举第一个点,这时候先转移这个点的状态,然后再枚举第二个点,当枚举的第二个点都转移完状态后,就跳出第一个点的循环。
第一次写的代码
#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
*/