您的位置:首页 > 其它

魔法物品

2016-01-30 21:31 351 查看
魔法物品

有两种类型的物品:普通物品和魔法物品。普通物品没有魔法属性,而魔法物品拥有一些魔法属性。每种普通物品有一个价值P,但每种魔法物品有两种价值:鉴定前的价值P。和鉴定后的价值P2(当然,P2总是大于P。)。

为了鉴定一个魔法物品,你需要购买一个鉴定卷轴,用它来鉴定魔法物品。鉴定完一件魔法物品以后,鉴定卷轴便会消失。每个鉴定将会消耗Pi元钱,如果没有足够的钱,你将无法购买任何鉴定卷轴。

现在,你正在一个集市中,同时拥有很多物品。你知道每件物品的价值并且想要出售全部物品。那么,你最多能够获得多少钱呢?

你可以假定:

★开始的时候你没有钱。

★所有的魔法物品都还没有被鉴定。

★只要你有足够的钱,你可以购买任意多的鉴定卷轴。

输入magic.in

第一行有两个整数N和Pi(0<Pi≤5000),表示你拥有的物品数和一个鉴定卷轴价格。

接下来N行,每行给出一件物品的价格。

对于每件普通物品,那一行仅有一个整数P(0<P≤10000)。

对于每件魔法物品,那一行将会有两个整数P1和P2(0<P1<P2≤10000)。

输出magic.out

一个整数表示你最多能够获得多少钱。

样倒输入

2 10

10

20 100

样例输出

100

数据规模

对于30%的数据N≤50;

对于100%的数据N≤1000。

这道题刚开始和bzoj项链那道题弄混了,觉得可以先购买鉴定卷轴,先花钱后付账,可是后来发现并不是这么简单,因为如果把所有不必用鉴定卷轴的物品的钱加起来还无法买一个卷轴的话,那么还须用从鉴定的物品中舍弃一些,来凑钱买鉴定卷轴。所以刚开始的想法很显然错了。

于是重新动工

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,i,j,k,p;
int a[1003],b[1003],cha[1003];
int f[10000003],g[10000003];
int num1,num2,money,ans;
int main()
{
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
scanf("%d%d\n",&n,&p);
for (i=1;i<=n;i++)
{
char s[100];
gets(s);
int len=strlen(s);
j=0;
int x=0,y=0;
while (j<len&&s[j]!=' ')
{
x=x*10+s[j]-48;
j++;
}
j++;
while (j<len)
y=y*10+s[j]-48,j++;
if (y==0||y-x<=p)
money+=x;
else
num1++,num2+=y,a[num1]=x,b[num1]=y,cha[num1]=y-x,ans+=cha[num1];
}
if (money>=p)
{
for (i=1;i<=num1;i++)
money+=b[i];
money-=p*num1;
}
else
{
for (i=1;i<=num1;i++)
for (j=ans;j>=cha[i];j--)
if (f[j-cha[i]]+a[i]>f[j])
f[j]=f[j-cha[i]]+a[i],g[j]=g[j-cha[i]]+1;
else
if (f[j-cha[i]]+a[i]==f[j])
g[j]=max(g[j],g[j-cha[i]]+1);
int maxn=0;
for (j=1;j<=ans;j++)
if (f[j]+money>=p)
{
maxn=max(maxn,(money+num2-j-(num1-g[j])*p));
}
cout<<maxn<<endl;
}
}
但是这个方法的时间复杂度太高,根本无法承受,况且未考虑一个鉴定卷轴也不买的情况。本渣也不得不接受这个现实

于是有了现在的代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,i,j,k,p;
int a[1003],b[1003],cha[1003];
int f[10000003],g[10000003];
int num1,num2,money,ans;
int main()
{
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
scanf("%d%d\n",&n,&p);
for (i=1;i<=n;i++)//略长的读入处理
{
char s[100];
gets(s);
int len=strlen(s);
j=0;
int x=0,y=0;
while (j<len&&s[j]!=' ')
{
x=x*10+s[j]-48;
j++;
}
a[i]=x;//a存储不用鉴定卷轴的价值
j++;
while (j<len)
y=y*10+s[j]-48,j++;
num1+=x;//不用卷轴的最大价值
b[i]=y-p-x;//比存储的是用卷轴比不用卷轴实际多出来的钱
if (b[i]>0)
num2+=a[i]+b[i];
else
b[i]=0,num2+=a[i];
}
memset(f,127/3,sizeof(f));
if (num1<p) <span style="font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.2000007629395px;"> {</span>
cout<<num1<<endl;
return 0;
}//如果不用卷轴的最大价值都无法买一个卷轴,那么只好直接销售了
g[0]=1; f[0]=0;
for (i=1;i<=n;i++)
for (j=p-1;j>=0;j--)
if (g[j])
{
k=j+a[i];
if (k>p) k=p;
if (f[j]+b[i]<f[k])
{
f[k]=f[j]+b[i];
g[k]=1;
}
}//计算凑够一个卷轴所需的最小损失,因为只要买的了一个卷轴,那么接下来所以用卷轴的物品挣得的钱一定可以再买卷轴
printf("%d",num2-f[p]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: