原题链接:poj 3042 Grazing on the Run
大致题意是:有n颗草,牛初始位置在L,要吃光所有的草,其中牛每单位时间走一个单位,且每棵草每个时间都会枯萎1个单位,求吃到草的枯萎度之和最小是多少。可以根据Hint yy出题意。
由于每次当前的选择都会对以后造成影响,故每次选择时应该把对以后的影响加入到当前的dp值中
用dp[i][j][0]表示牛吃光了i-j之间的草之后再i位置时的最小值,而用dp[i][j][1]表示在j位置时的最小值,则式子:
dp[i][j][0]=min(dp[i+1][j][0]+(n-j+i)*(a[i+1]-a[i]),dp[i+1][j][1]+(n-j+i)*(a[j]-a[i]));
dp[i][j][1]=min(dp[i][j-1][1]+(n-j+i)*(a[j]-a[j-1]),dp[i][j-1][0]+(n-j+i)*(a[j]-a[i]));
最后别忘了排序,他的顺序不一定是有序的额~~~
渣渣代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1005
using namespace std;
int dp[N][N][2];
int a[N];
int n,s;
int pos;
int solve()
{
memset(dp,0x3f,sizeof(dp));
dp[pos][pos][0]=dp[pos][pos][1]=0;
for(int i=pos; i>=0; i--)
for(int j=pos; j<n; j++)
{
if(i==pos&&j==pos)continue;
dp[i][j][0]=min(dp[i+1][j][0]+(n-j+i)*(a[i+1]-a[i]),dp[i+1][j][1]+(n-j+i)*(a[j]-a[i]));
dp[i][j][1]=min(dp[i][j-1][1]+(n-j+i)*(a[j]-a[j-1]),dp[i][j-1][0]+(n-j+i)*(a[j]-a[i]));
}
return min(dp[0][n-1][0],dp[0][n-1][1]);
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&s);
pos=-1;
bool flag=false;
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
sort(a,a+n);
for(int i=0; i<n; i++) //把初始位置点在原序列找出来,如果没有直接加入原序列,对结果没有影响
{
if(a[i]==s)
{
flag=true;
pos=i;
break;
}
if(a[i]>s)
{
pos=i;
for(int j=n-1; j>=i; j--)
a[j+1]=a[j];
a[i]=s;
n++;
flag=true;
break;
}
}
if(!flag)
{
n++;
a[n-1]=s;
pos=n-1;
}
printf("%d\n",solve());
return 0;
}