【DP】Occult的卡片升级计划 校OJ2389

题目描述

Occult喜欢玩一款手游,手游中有很多好看的卡片。他想要升级这些卡。
现在他有m块经验石,目标是强化一张卡片,卡片最开始的时候是0级,卡片会升级,而升级所需的经验会越来越多。
假设卡片满级是n级,给出a[1],a[2]....a[n],a[i]表示从i-1级升到i级所需的经验石数量。保证a[1]+a[2]+...+a[n]=m,且a[1]<=a[2]<=..<=a[n]。
然而每次强化是要付钱的,并且每次加的经验石的数量是有限的,最多为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元。

输入

多组测试数据。
每组测试数据第一行输入n,m。(0<n<=m<=100000)
第二行输入n个整数a[1],a[2]......,a[n]。
保证a[1]+a[2]+...+a[n]=m,且a[1]<=a[2]<=..<=a[n]。

输出

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

样例输入

2 15
5 10

样例输出

1

#include <bits/stdc++.h>
using namespace std;

const int mn=100010;
const long long inf=1e18;

int n,m;
int a[mn],s[mn];
long long dp[mn];

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		s[0]=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			s[i]=s[i-1]+a[i];   //升到i级时所需总卡片数
		}  

		for(int i=0;i<=m;i++)
			dp[i]=inf;
		dp[0]=0;

		for(int i=1;i<=m;i++)
		{
			for(int j=1;j<=min(10,i);j++)
			{
				int q=upper_bound(s+1,s+n+1,i-j)-s-1;  //i-j时等级
				dp[i]=min(dp[i],dp[i-j]+j*q);  //用i张卡时最少花费
			}
		}

		printf("%lld\n",dp[m]);
	}
    return 0;
}



猜你喜欢

转载自blog.csdn.net/ummmmm/article/details/80407628
今日推荐