Cool(动态规划)

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
#include
#include
#include
#include
#include
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<return 0;
}
/*
5 3
4 7 2 5 -3 6
*/

Cool(动态规划)_第1张图片

你可能感兴趣的:(#,日常训练赛,动态规划)