景观美化【DP】

>Description
花园是由N块花圃组成的。第i块花圃初始的时候有Ai数量的泥土,要使得第i块花圃的泥土数量Ai变成Bi。
约翰有三个选择:第一,他可以买一个单位的泥土放进任意花圃中,代价是X;第二,他可以将一个单位的泥土从某一个花圃中除去,代价是Y;第三,他可以将第i块花圃中的一个单位的泥土搬运到第j块花圃中,代价是Z*|i-j|。
请帮助约翰计算为了达到目的最小需要花费的代价。


>Input
第一行四个整数,分别是N,X,Y,Z。
接下来N行,每行两个整数,分别表示Ai和Bi。

>Output
只有一行一个整数,表示最小的代价。


>Sample Input
4 100 200 1
1 4
2 3
3 2
4 0

>Sample Output
210

数据范围:1<=N<=100,0<=Ai,Bi<=10,0<=X,Y,Z<=1000。


>解题思路
我们要把花园的泥土都按照泥土计算单位分开来存储,例如,输入样例的数字存储为:122333444和111122233,一个1表示第一块花圃有1块泥土,两个2表示第二块花圃有2块泥土。

使用DP:
f[i][j]表示把前i个单位的泥土变为前j个单位的泥土的最小代价。
根据题意,有3种变法:
1购买:f[i][j-1]+x,表示前j-1块泥土都处理好了,再买一块泥土补充到第j块。
2除去:f[i-1][j]+y,表示用前i-1块泥土变为前j块泥土,多出的第i块泥土除掉。
3搬运:f[i-1][j-1]+z*|a[i]-b[j]|,表示前i-1块泥土变为前j-1块泥土,把第i块泥土搬运到第j块。


>代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,x,y,z,a[1005],b[1005],aa,bb,ta,tb,f[1005][1005];
int main()
{
	memset(f,0x7f,sizeof(f)); //赋值
	scanf("%d%d%d%d",&n,&x,&y,&z);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&aa,&bb);
		for(int j=1;j<=aa;j++)
		 a[++ta]=i;
		for(int j=1;j<=bb;j++)
		 b[++tb]=i; //存储方式
	}
	f[0][0]=0;
	for(int i=0;i<=ta;i++)
	 f[i][0]=i*y;
	for(int i=0;i<=tb;i++)
	 f[0][i]=i*x; //预处理
	for(int i=1;i<=ta;i++)
	 for(int j=1;j<=tb;j++)
	  f[i][j]=min(f[i-1][j-1]+z*max(a[i]-b[j],b[j]-a[i]),min(f[i-1][j]+y,f[i][j-1]+x)); //状态转移方程
	printf("%d",f[ta][tb]);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值