您的位置:首页 > Web前端

ZUFE2389: Occult的卡片升级计划(DP)

2016-05-17 23:12 309 查看


2389: Occult的卡片升级计划


Description

Occult喜欢玩一款手游,手游中有很多好看的卡片。他想要升级这些卡。

现在他有m块经验石,目标是强化一张卡片,卡片最开始的时候是0级,卡片会升级,而升级所需的经验会越来越多。

假设卡片满级是n级,给出a[1],a[2]....a
,a[i]表示从i-1级升到i级所需的经验石数量。保证a[1]+a[2]+...+a
=m,且a[1]<=a[2]<=..<=a


然而每次强化是要付钱的,并且每次加的经验石的数量是有限的,最多为10个。

每一次强化要付的金钱等于这一次加的经验石的数量乘上当前卡片的等级。

Occult想知道要把这张卡片从0级升到满级最少需要支付多少金钱。

例如输入:

2 15

5 10

表示卡片满级是2级,现在有15块经验石。第0级升到第1级所需的经验石数量是5个,第1级升到第2级所需的经验石数量是10个。

我们可以采取以下升级策略,使得支付的金钱最少:

[第一次强化]

加4个经验石。这次强化的费用:0级×4个石头=0元。强化之后升到了0级。

[第二次强化]

加10个经验石。这次强化的费用:0级×10个石头=0元。强化之后升到了1级。

[第三次强化]

加1个经验石。这次强化的费用:1级×1个石头=1元。强化之后升到了2级。

强化完毕,把三次的花费加起来,是1元。

Input

多组测试数据。

每组测试数据第一行输入n,m。(0<n<=m<=100000)

第二行输入n个整数a[1],a[2]......,a


保证a[1]+a[2]+...+a
=m,且a[1]<=a[2]<=..<=a


Output

对于每组测试数据,输出卡片从0级升到满级需要支付的最少金钱。

Sample Input

2 15
5 10


Sample Output

1




______________________________________________________________________________________________________________________

我们要考虑当升级第i张卡片时它的最小花费为从i-10到i-1之间的卡片花费加上这次升级的花费其中的最小值;
即 s[i]=min(s[i-1]+k[i-1]*1,s[i-2]+k[i-2]*2,……,s[i-10]+k[i-10]*10])数组k表示用k快经验石后的等级。
根据这个关系容易写出代码

#include <iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int min(int a, int b)
{
return (a < b) ? a : b;

}
int main()
{
int m, n, a[100005], cnt, tot, sum;
long long int s[100005], mn, k[100005], j;
while (~scanf("%d%d", &n, &m))
{

for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
cnt = 0;
tot = 2;
sum = a[1];
memset(k, 0, sizeof(k));
for (int i = 0; i <= m; i++)
{
if (i>=sum)
{
cnt++;
sum += a[tot++];
}
k[i] += cnt;
}
s[0] = 0;
for (int i = 1; i <= m; i++)
{
mn = s[i - 1] + k[i - 1];
for (j = 1; j <= 10; j++)
{
if (j>i)
break;
mn = min(mn, s[i - j] + k[i - j] * j);
}
s[i] = mn;
}
printf("%lld\n", s[m]);
}
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: