Description
农夫约翰的牧场围栏上出现了一个洞,有N(1 <= N <= 1,000)只牛从这个洞逃出了牧场。这些出逃的奶牛很狂躁,他们在外面到处搞破坏,每分钟每头牛都会给约翰带来1美元的损失。约翰必须用缰绳套住所有的牛,以停止他们搞破坏。
幸运的是,奶牛们都在牧场外一条笔直的公路上,牧场的大门恰好位于公里的0点处。约翰知道每头牛距离牧场大门的距离P_i(-500,000 <= P_i <= 500,000, P_i != 0)
约翰从农场大门出发,每分钟移动一个单位距离,每到一头牛所在的地点,约翰就会给它套上缰绳,套缰绳不花时间。按怎样的顺序去给牛套缰绳才能使约翰损失的费用最少?
Input
第一行,1个整数N
接下来N行,每行一个整数,表示每头牛的位置
Output
一个整数,表示所求答案
Sample Input
4
-2
-12
3
7
Sample Output
50
【分析】
显然是DP。我们记录状态f[i][j][k]表示从起点开始,左边套了i头牛,右边套了j头牛,当前位置在k(0表示在最左边,1表示在最右边)的最优值。
处理的时候,我用数组A[]记录:在起点左边的牛离起点的距离,从小到大排序。有n个元素。
数组B[]记录:在起点右边的牛离起点的距离,从小到大排序。有m个元素。
于是,我们得到状态转移方程:
f[i][j][0]=min{
f[i-1][j][0]+(A[i]-A[i-1])*(m-j+n-(i-1)),
f[i-1][j][1]+(B[j]+A[i])*(m-j+n-(i-1))
}
f[i][j][1]=min{
f[i][j-1][0]+(B[j]+A[i])*(n-i+m-(j-1)),
f[i][j-1][1]+(B[j]-B[j-1])*(n-i+m-(j-1))
}
最后min(f[n][m][0],f[n][m][1])即为答案。
【代码】
/************************
ID:Ciocio
LANG:C++
DATE:2013-12-21
TASK:Escape
************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 1005
int N,n,m;
int A[MAXN],B[MAXN],f[MAXN][MAXN][2];
void _read(int &x,bool mark=0)
{
char tt=getchar();
while(tt<'0'||'9'<tt){if(tt=='-') mark=1;tt=getchar();}
for(x=0;'0'<=tt&&tt<='9';x=(x<<3)+(x<<1)+tt-'0',tt=getchar());
x=mark?-x:x;
}
void _init()
{
_read(N);
for(int i=1,x;i<=N;i++)
{
_read(x);
if(x<0) A[++n]=-x; //在左边,放入A[]数组
if(x>0) B[++m]=x; //在右边,放入B[]数组
}
}
void _solve()
{
sort(A+1,A+n+1);
sort(B+1,B+m+1);
for(int i=1;i<=n;i++) //边界
{
f[i][0][0]=f[i-1][0][0]+(A[i]-A[i-1])*(m+n-(i-1));
f[i][0][1]=f[i][0][0]+A[i]*(m+n-(i-1));
}
for(int i=1;i<=m;i++)
{
f[0][i][1]=f[0][i-1][1]+(B[i]-B[i-1])*(n+m-(i-1));
f[0][i][0]=f[0][i][1]+B[i]*(n+m-(i-1));
}
for(int i=1;i<=n;i++) //DP
for(int j=1;j<=m;j++)
{
f[i][j][0]=min(
f[i-1][j][0]+(A[i]-A[i-1])*(m-j+n-(i-1)),
f[i-1][j][1]+(B[j]+A[i])*(m-j+n-(i-1))
);
f[i][j][1]=min(
f[i][j-1][0]+(B[j]+A[i])*(n-i+m-(j-1)),
f[i][j-1][1]+(B[j]-B[j-1])*(n-i+m-(j-1))
);
}
cout<<min(f[n][m][1],f[n][m][0])<<endl;
}
int main()
{
_init();
_solve();
return 0;
}