Cool(动态规划)

来源:互联网 发布:windows平板电脑刷机 编辑:程序博客网 时间:2024/06/06 01:51

Cool

(LYOI20171011模拟赛第一试第三题)
(cool.* 时间空间限制: 1S, 128M)
题目描述:
Tky 来到一个雄奇的金字塔挖宝,但是这是一座被诅咒的金字塔, Tky 必须马上逃离这里,
否则 Tky 就会被埋在金字塔里,但他不希望此行落空。
现在 Tky 面前有 N+1 种财宝,每种财宝都有一个价值。第一种财宝重量为 0,第二种财
宝重量为 1,总之第 I 种财宝重量为 I-1。现在 Tky 希望拿走 N+M 个物品,但是这 M+N 个
物品总重量不能超过 N。 Tky 希望能获得最大的价值。你能帮帮他吗?
由于金字塔跟 Tky 一样牛,所以每种财宝无限个。
输入格式:
第一行两个正整数 N, M
第二行 N+1 个整数,第 I 个整数代表了第 I 种财宝的价值输出格式:
一个数,表示最大利润。
样例输入:
5 3
4 7 2 5 -3 6
样例输出:
47
数据范围:
10%满足 N,M<=10
40%满足 N,M<=100
100%满足 N,M<=3000 abs(财宝价值)<=1000

思路

【Cool】
这是一个比较特殊的动态规划,首先要注意到因为要取到N+M个,所以我们可以知道每一次至少要拿走M件0号物品,所以我们的初始化就是这样。
for(i=0;i<=n;i++)
f[i]=(n+m)*a[0];
对于这样的完全背包问题,我们需要找到一个动态规划转移方程。f[i]表示i的体积下最多得到的价值,f[j]+a[i]-a[0]是从j空间转移而来,所以f[j]+a[i]-a[0]中-a[0]的原因是:我们模拟出来在执行之前,全部都装满了0号物品,所以我们在转移的时候,需要取出一个0号物品,再塞进去一个i号物品。
f[i+j]=max(f[j]+a[i]-a[0],f[i+j]);
注意一下,这里的数据是有负数的,所以读入优化的大佬们就要注意特判负数。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int i,j,m,n,k,l;int a[3010];int r(){    int aans=0,f=1;    char ch=getchar();    while(ch>'9'||ch<'0')    {        if(ch=='-')        f=-1;        ch=getchar();    }    while(ch<='9'&&ch>='0')    {        aans*=10;        aans+=ch-'0';        ch=getchar();    }    return aans*f;}int ans,f[10004];int main(){    freopen("cool.in","r",stdin);    freopen("cool.out","w",stdout);    n=r(),m=r();    int ans=0;    for(i=0;i<=n;i++)    a[i]=r();    for(i=0;i<=n;i++)    f[i]=(n+m)*a[0];    for(i=1;i<=n;i++)    for(j=0;j<=n-i;j++)    f[i+j]=max(f[j]+a[i]-a[0],f[i+j]);    cout<<f[n];    return 0;}/*5 34 7 2 5 -3 6*/

这里写图片描述

原创粉丝点击