链接:点击打开链接
题意:在一条直线上有n个施工队和m个避难所,给出每个施工队和避难所相对于原点的距离,求在保证每个避难点有一个施工队的前提下,所有施工队移动的最小距离和
代码:
#include <math.h>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const long long INF=0x3f3f3f3f;
struct node{
int d,id,cp;
}a[4005],b[4005];
bool cmp1(node x,node y){
return x.d<y.d;
}
bool cmp2(node x,node y){
return x.id<y.id;
}
long long dp[4005];
int path[4005][4005];
void print(int x,int y){
if(x)
print(x-1,path[x][y]);
a[x].cp=b[y].id;
}
int main(){ //dp[i][j]表示前i个施工队到前j个避难场所的距离和
int n,m,i,j;
while(scanf("%d",&n)!=EOF){
for(i=0;i<n;i++){
scanf("%d",&a[i].d);
a[i].id=i;
}
scanf("%d",&m);
for(i=0;i<m;i++){
scanf("%d",&b[i].d);
b[i].id=i;
}
sort(a,a+n,cmp1); //先按距离排序,保证最优
sort(b,b+m,cmp1);
memset(dp,INF,sizeof(dp));
memset(path,0,sizeof(path));
dp[0]=abs(a[0].d-b[0].d);
for(i=1;i<n;i++){
for(j=min(i,m-1);j>=0;j--){
if(j>0&&dp[j-1]<dp[j]){ //dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+abs(a[i].d-b[j].d)
path[i][j]=j-1; //然后实际过程中可以省略第一维
dp[j]=dp[j-1]+abs(a[i].d-b[j].d);
}
else{
path[i][j]=j;
dp[j]=dp[j]+abs(a[i].d-b[j].d);
}
}
}
printf("%lld\n",dp[m-1]);
print(n-1,m-1);
sort(a,a+n,cmp2);
for(i=0;i<n;i++)
printf("%d ",a[i].cp+1);
printf("\n");
}
return 0;
}