背景 Background 

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

描述 Description

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

输入格式 Input Format 

   第一行八个正整数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 )

输出格式 Output Format 

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

 

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<iostream>
#include<cstdlib>
using namespace std;
int money,n,s1,s2,cost1,cost2,red,blue,ans;
struct node
{ 
       int win,gold;
}d[110];
int f[11][1010],g[11][1010],last[11][1010]={1};
int cmp(const void *a,const void *b)
{
    return (*(node *)a).win-(*(node *)b).win;
}
int main()
{
    int i,j,k;
    cin>>money>>n>>s1>>s2>>cost1>>cost2>>red>>blue;
    for (i=1;i<=n;i++) cin>>d[i].win>>d[i].gold;
    qsort(d+1,n,sizeof(node),cmp);
    g[0][0]=money;
    for (i=0;i<=s1;i++)
      for (j=0;j<=s2;j++)
      {
          if (i>=1)
          if (g[i-1][j]>=cost1)
          if (f[i][j]<f[i-1][j]*red)
          {
                                    f[i][j]=f[i-1][j]*red;
                                    g[i][j]=g[i-1][j]-cost1;
                                    if (f[i][j]>ans)ans=f[i][j];
                                    for (k=last[i-1][j];k<=n;k++)
                                         if (f[i][j]>=d[k].win) g[i][j]+=d[k].gold;else break;
                                     last[i][j]=k;
          }
          if (j>=1)
          if (g[i][j-1]>=cost2)
          if (f[i][j]<f[i][j-1]+blue)
          {
                                     f[i][j]=f[i][j-1]+blue;
                                     g[i][j]=g[i][j-1]-cost2;
                                     if (f[i][j]>ans) ans=f[i][j];
                                     for (k=last[i][j-1];k<=n;k++)
                                         if (f[i][j]>=d[k].win) g[i][j]+=d[k].gold;else break;
                                     last[i][j]=k;
          }
      }
    cout<<ans<<endl;
    return 0;
}