NOIP模拟题——Landscaping
2. Landscaping
题目描述
N(1 <= N <= 100)个数排成一行,值分别为A_i,现在希望把每个数对应地改成B_i。(A_i,B_i的值均在0..10之间)。改变的方式有3种:
(1)把A_i增加到B_i,每增加1,花费$X
(2)把A_i减少到B_i,每减少1,花费$Y
(3)把第i个数的值转移到第j个数,每转移1,花费为$Z*|i-j|
问:最小的花费是多少。
输入
第1行:4个整数 N, X, Y, Z (0 <= X, Y, Z <= 1000).
第2..1+N行: 每行2个整数 A_i 和 B_i.
输出
第1行:1个整数,表示最小的花费。
样例输入
4 100 200 1
1 4
2 3
3 2
4 0
样例输出
210
提示
INPUT DETAILS: There are 4 flowerbeds in a row, initially with 1, 2, 3, and 4 units of dirt. Farmer John wishes to transform them so they have 4, 3, 2, and 0 units of dirt, respectively. The costs for adding, removing, and transporting dirt are 100, 200, and 1.
OUTPUT DETAILS: One unit of dirt must be removed (from flowerbed #4), at a cost of 200. The remaining dirt can be moved at a cost of 10 (3 units from flowerbed #4 to flowerbed #1, 1 unit from flowerbed #3 to flowerbed #2).
***********************************************************************
由于加或减不一定要加完,可以将每个数拆分成几个代表单位1的数(保存编号)。
考虑DP。F[I][J]表示A数组的I状态和B数组的J状态要相等的话,最小的花费。
由于拆成单位1,所以状态转移方程:
f[i][j]=min(f[i][j],f[i-1][j]+Y);//增加X
f[i][j]=min(f[i][j],f[i][j-1]+X);//增加y等价于降低x
f[i][j]=min(f[i][j],f[i-1][j-1]+abs(a[i]-b[j])*Z);
初值:当I状态为0时,要变成j状态只能都加X;当J状态为0时,要变成I状态只能都加X(即A数组减Y)
1 #include<cstdio>
2 #include<iostream>
3 #include<cstring>
4 #include<cmath>
5 using namespace std;
6 const int maxn=1005;
7 int a[maxn],b[maxn];
8 int temp1,temp2;
9 int f[maxn][maxn];
10 int n,X,Y,Z;
11 inline int abs(int x)
12 {
13 if(x<0)return -x;
14 return x;
15 }
16 int main()
17 {
18 freopen("landscaping.in","r",stdin);
19 freopen("landscaping.out","w",stdout);
20 scanf("%d%d%d%d",&n,&X,&Y,&Z);
21 for(int i=1;i<=n;i++)
22 {
23 int x,y;
24 scanf("%d",&x);
25 while(x)
26 {
27 a[++temp1]=i;
28 x--;
29 }
30 scanf("%d",&y);
31 while(y)
32 {
33 b[++temp2]=i;
34 y--;
35 }
36 }
37 for(int i=1;i<=temp1;i++)//增加y等价于降低x
38 f[i][0]=Y*i;
39 for(int j=1;j<=temp2;j++)
40 f[0][j]=X*j;//增加x
41 for(int i=1;i<=temp1;i++)
42 for(int j=1;j<=temp2;j++)
43 {
44 f[i][j]=1e8;
45 f[i][j]=min(f[i][j],f[i-1][j]+Y);//增加X
46 f[i][j]=min(f[i][j],f[i][j-1]+X);//增加y等价于降低x
47 f[i][j]=min(f[i][j],f[i-1][j-1]+abs(a[i]-b[j])*Z);
48 }
49 printf("%d",f[temp1][temp2]);
50 return 0;
51 }