购买气球

来源:互联网 发布:知鱼怎么烧 编辑:程序博客网 时间:2024/06/11 02:58

背景 Background

    小Q玩开采金钱游戏因为赚了太多钱,而这些钱又没有用,所以他相当愤怒,投诉了出品游戏者。所以游戏出品者就推出了《购买气球》这一款游戏,这一游戏是可以使用经营餐厅游戏获得的钱的。

描述 Description

    小Q在经营餐厅中赚下了Money元,这些钱可以用来从商店买红色或者蓝色的气球,打破一个红色气球可以让分数score变为原来的red倍,打破一个蓝色的气球可以让分数score加上blue,每当你的分值score到达一个值win[i](score>=win[i])可以获得额外奖励金钱gold[i]。
    当然,开始小Q得到的分值为0。
    注:任何操作或奖励前后都不能欠钱(money不能小于0)。

输入格式 InputFormat

    第一行八个正整数Money,N,S1,S2,cost1,cost2,red,blue。表示有N个奖励方案,商店有S1个红色气球,S2个蓝色气球,买一个红色气球要花费cost1元,买一个蓝色气球需要cost2元。Money,red,blue意思为题目所示。( 1 <= red <= 3 ,1 <= blue <= 10 )
    接下来N行,每行两个正整数win[i],gold[i],意义如题目所示。( 1 <= win[i] <= 10^8 , 1 <= gold[i] <= 10^6 )

输出格式 OutputFormat

    一个数Max表示最多能得到的分数。(我们无视金钱)

样例输入 SampleInput 

2 2 5 6 2 2 3 101 12 1

样例输出 SampleOutput 

30

数据范围和注释 Hint

    样例中有5个红色气球和6个蓝色气球,红色气球和蓝色气球都要2元,红色气球能让分值成为3倍,蓝色气球能让分值加上10。
    样例先买蓝色气球一个,用了2元,没钱了。打破它,分值加10,变为10,由于到达了奖励方案1和奖励方案2的值(win[i]),被奖励2(gold[1] +gold[2]=1+1=2)元,这两元用来买红色气球,打破它,分值变为3倍,即30,钱用完。
40%的数据:1 <= S1 <= 5 ,1 <= S2 <= 10
100%的数据:1 <= Money <= 10^6 ,1 <= N <= 100 , 1 <= S1 <= 10 , 1 <= s2 <= 1000
思路:dp
/*DP,用f[i][j]表示买了i个红气球,j个蓝气球的最优分数,g[i][j]表示买了i个红气球,j个蓝气球的剩余钱数,将win升序排序last[i][j]表示在[i][j]状态已经使用了前last[i][j]次的奖励。边界 last[][]={1};g[0][0]=money;f[0][0]=0;状态转移方程 f[i][j]=max{f[i-1][j],f[i][j-1]} (0<=i<=s1,0<=j<=s2;i,j不同时等于0)g[i][j],last[i][j]随之更新。*/#include <stdio.h>#include <algorithm>using namespace std;typedef struct Node{int win;int gold;}node;int dp[11][1001], g[11][1001], last[11][1001];node wing[101];bool cmp(node a, node b){return a.win < b.win;}int main(){int money, n, s1, s2, cost1, cost2, red, blue, i, j, k, ans = 0;scanf("%d%d%d%d%d%d%d%d", &money, &n, &s1, &s2, &cost1, &cost2, &red, &blue);for(i = 0; i < n; i++){scanf("%d%d", &wing[i].win, &wing[i].gold);}sort(wing, wing+n, cmp);g[0][0] = money;for(i = 0; i <= s1; i++){for(j = 0; j <= s2; j++){last[i][j] = 0;if(i >= 1 && g[i-1][j] >= cost1 && dp[i][j] < dp[i-1][j]*red){dp[i][j] = dp[i-1][j]*red;g[i][j]  = g[i-1][j] - cost1;if(dp[i][j] > ans){ans = dp[i][j];}for(k = last[i-1][j]; k < n; k++){if(dp[i][j] >= wing[k].win){g[i][j] += wing[k].gold;}else{break;}}last[i][j] = k;}if(j >= 1 && g[i][j-1] >= cost2 && dp[i][j] < dp[i][j-1]+blue){dp[i][j] = dp[i][j-1]+blue;g[i][j] = g[i][j-1] - cost2;if(dp[i][j] > ans){ans = dp[i][j];}for(k = last[i][j-1]; k < n; k++){if(dp[i][j] >= wing[k].win){g[i][j] += wing[k].gold;}else{break;}}last[i][j] = k;}}}printf("%d\n", ans);return 0;}


0 0
原创粉丝点击