USACO The Cow Run

USACO The Cow Run

洛谷传送门

JDOJ传送门1

JDOJ传送门2

Description

Problem 1: The Cow Run [Chris Tzamos, 2006]

Farmer John has forgotten to repair a hole in the fence on his farm, and
his N cows (1 <= N <= 1,000) have escaped and gone on a rampage! Each
minute a cow is outside the fence, she causes one dollar worth of damage.
FJ must visit each cow to install a halter that will calm the cow and stop
the damage.

Fortunately, the cows are positioned at distinct locations along a straight
line on a road outside the farm. FJ knows the location P_i of each cow i
(-500,000 <= P_i <= 500,000, P_i != 0) relative to the gate (position 0)
where FJ starts.

FJ moves at one unit of distance per minute and can install a halter
instantly. Please determine the order that FJ should visit the cows so he
can minimize the total cost of the damage; you should compute the minimum
total damage cost in this case.

Input

* Line 1: The number of cows, N.

* Lines 2..N+1: Line i+1 contains the integer P_i.

Output

* Line 1: The minimum total cost of the damage.

Sample Input

4 -2 -12 3 7

Sample Output

50

HINT

INPUT DETAILS:

Four cows placed in positions: -2, -12, 3, and 7.

OUTPUT DETAILS:

The optimal visit order is -2, 3, 7, -12. FJ arrives at position -2 in 2
minutes for a total of 2 dollars in damage for that cow.

He then travels to position 3 (distance: 5) where the cumulative damage is
2 + 5 = 7 dollars for that cow.

He spends 4 more minutes to get to 7 at a cost of 7 + 4 = 11 dollars for
that cow.

Finally, he spends 19 minutes to go to -12 with a cost of 11 + 19 = 30 dollars.

The total damage is 2 + 7 + 11 + 30 = 50 dollars.


题解:

一道区间DP的还很好的题目。

拿到题之后首先就会发现这个正负比较难搞。

但是仔细思考一下我们就可以发现,答案其实只与两点之间的距离有关,与正负并无关。并且,我们可以发现,套牛的顺序一定是按单调的,也就是说,路过的牛必须都套上,否则的话那你岂不是沙茶。

所以这个区间应该是连续的,考虑使用排序+区间DP解决。

至于正负,加一维状态表示其在零点左侧还是零点右侧。零点可以另开一个点存。

具体见代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 1002
int n;
int dp[maxn][maxn][2];
int pos[maxn];
int main()
{
    scanf("%d",&n);
    memset(dp,0x3f,sizeof(dp));
    for(int i=1;i<=n;i++)
        scanf("%d",&pos[i]);
    sort(pos+1,pos+1+n);
    int c=lower_bound(pos+1,pos+1+n,0)-pos;
    for(int i=n;i>=c;i--) 
        pos[i+1]=pos[i];
    pos[c]=0;
    dp[c][c][1]=0;
    dp[c][c][0]=0;
    for(int len=2;len<=n+1;len++)
        for(int i=1;i+len-1<=n+1;i++)
        {
            int j=i+len-1;
            dp[i][j][0]=min(dp[i+1][j][0]+(pos[i+1]-pos[i])*(n-j+i+1),dp[i+1][j][1]+(pos[j]-pos[i])*(n-j+i+1));
		    dp[i][j][1]=min(dp[i][j-1][1]+(pos[j]-pos[j-1])*(n-j+i+1),dp[i][j-1][0]+(pos[j]-pos[i])*(n-j+i+1));
        }
    printf("%d",min(dp[1][n+1][0],dp[1][n+1][1]));
    return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/13824558.html