您的位置:首页 > 其它

[noip模拟题]仔排

2017-10-05 10:28 169 查看
Description

wpf深知买仔排的不易(食堂好黑的!),于是经过深思熟虑,wpf决定自己卖仔排!想我们wpf可是从事经济研究的,做买卖可难不倒wpf!经过几个日夜的钻研,wpf得出一个很重要的结论:低价买,高价卖。一块仔排进价只有1元,如果以2元卖出,不就赚钱了嘛!接下来,就要考虑运货问题了。手推车既轻便又环保,乃是居家旅行做生意之必备武器,正巧wpf就有一辆。每次,他都可以去批发商那里运一车仔排到常外去。可惜wpf力气有限,一次只能运最多K块仔排(手推车很轻,重量不计),再多wpf就推不动了。最开始,wpf手中有X元人民币。之后的每天,wpf都有三种选择:买进若干块仔排,卖出若干块仔排,或者自己吃掉一些仔排。三种选择中,他每天只能选一种。仔排的价格是固定的,买进1元,卖出2元。他可以一次买进任意数量的仔排,只要他有足够的钱,并且买下这批仔排后,他所有仔排的数量不能超过K,也不能超过V(wpf是用手推车存仔排的,多了存不下,重了推不动)。如果他当日手中有仔排,他也可以选择卖出任意数量,因为常外的小朋友们是那么热爱椒盐仔排,卖多少都会被抢购一空。他还可以选择吃掉手中部分或全部的仔排,这样一来,wpf就会迅速长壮,他一次就可以运送更多货物。说具体一些,每吃一块仔排,最大运货量K的值就会增加1。当然,手推车有个容量V,即使wpf的力气再大,一次运送仔排的数量也不能超过手推车的容量–也就是说,买进的仔排数量总是不超过V的。钱是好东西呀。
4000
不是有句话这么说来着:wpf赚钱,多多益善。那么在N天以内,wpf最多能得到多少钱呢?

Input

输入只有一行,包含了3个整数,依次为N,X,K和V。

N表示做生意的天数,X表示初始的资金,而K表示一开始wpf能运的最大仔排数量,V表示手推车的容量。

N≤100,X≤100,K≤50,V≤100

Output

输出一个整数,表示N天后wpf手中最多的现金数量。

Sample Input

8 5 1 5

Sample Output

10

提示

第一天买进一个仔排,花掉一块钱,手上还有4块钱。

第二天吃掉一个仔排,最大装货值变为2。

第三天买2个仔排,剩下2块钱。

第四天卖2个仔排,手上有6块钱。

第五到八天重复这一过程。

最后是10块钱。

这是最优方案。

HINT

DP

思路

看到数据范围,这道题时间复杂度肯定不小。实际上这道题的时间复杂度是O(n∗v3)的。令fi,j,k表示第i天结束后,拥有j块仔排,现在的最大容量为k的最多拥有的钱的数量。那么状态转移方程就是:

如果买入仔排:fi,j,k=max(fi,j,k,fi−1,L,k−(j−L))(其中L为变量,0<=L<=j)

如果卖出仔排:fi,j,k=max(fi,j,k,fi−1,L,k+(L−j)∗2)(其中L为变量,j<=L<=k)

如果吃掉仔排:fi,j,k=max(fi,j,k,fi−1,j−L,k+L)(其中L为变量,0<=L<=min(v−j,k))

这三个转移方程应该很好理解吧,注意一点:如果出现了负数是不行的,必须把这个较小的负数换成一个极大的负数(−inf),避免后面的状态由这个负数转移过来。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>

const int maxn=100;
const int inf=2000000000;

int n,x,m,v,ans;
int f[maxn+10][maxn+10][maxn+10];

int main()
{
scanf("%d%d%d%d",&n,&x,&m,&v);
memset(f[0],128,sizeof f);
f[0][0][std::min(v,m)]=x;
for(int i=1; i<=n; i++)
{
for(int j=0; j<=v; j++)
{
for(int k=j; k<=v; k++)
{
for(int l=0; l<=j; l++)
{
f[i][j][k]=std::max(f[i][j][k],f[i-1][l][k]-(j-l));
}
for(int l=j; l<=k; l++)
{
f[i][j][k]=std::max(f[i][j][k],f[i-1][l][k]+(l-j)*2);
}
for(int l=0; l<=std::min(v-j,k); l++)
{
f[i][j][k]=std::max(f[i][j][k],f[i-1][j+l][k-l]);
}
if(f[i][j][k]<0)
{
f[i][j][k]=-inf;
}
}
}
}
for(int i=0; i<=v; i++)
{
for(int j=0; j<=v; j++)
{
ans=std::max(ans,f
[i][j]);
}
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: