题意:
现在有n次游戏,每次都会有a[i]张牌,每张牌都会有一个花费和价值,每次游戏你拿的牌的花费不能超过3,当你拿完的时候,剩下的牌就被摧毁掉,并开始下一局游戏。如果你当前拿的牌的数量是10的倍数次,那么你当前这张牌的价值就会*2.问你最终最大价值是多少。
题解:
这种状态固定,并且靠枚举的题目一看就是记忆化搜索了。
那么
d
p
[
i
]
[
j
%
10
]
dp[i][j\%10]
dp[i][j%10]就表示到了第i次游戏,手上的牌的数量是j的时候,之后的答案最大是多少。
那么接下来就只有六种情况:
1,1 1,1 1 1,2,2 1,3
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+5;
struct node{
int num[4]={0};
vector<ll>vec[4];
}p[N];
ll dp[N][10];
int n,m;
ll dfs(int pos,int res){
if(pos>n)
return 0;
if(~dp[pos][res])
return dp[pos][res];
ll ans=0;
ans=dfs(pos+1,res);
if(p[pos].num[1]){
ll add=p[pos].vec[1][0];
if(res==9)
add*=2;
ans=max(ans,add+dfs(pos+1,(res+1)%10));
if(p[pos].num[2]){
add=p[pos].vec[1][0]+p[pos].vec[2][0];
if(res>=8)
add+=max(p[pos].vec[1][0],p[pos].vec[2][0]);
ans=max(ans,add+dfs(pos+1,(res+2)%10));
}
}
if(p[pos].num[2]){
ll add=p[pos].vec[2][0];
if(res==9)
add*=2;
ans=max(ans,add+dfs(pos+1,(res+1)%10));
}
if(p[pos].num[1]>=2){
ll add=p[pos].vec[1][0]+p[pos].vec[1][1];
if(res>=8)
add+=p[pos].vec[1][0];
ans=max(ans,add+dfs(pos+1,(res+2)%10));
}
if(p[pos].num[1]>=3){
ll add=p[pos].vec[1][0]+p[pos].vec[1][1]+p[pos].vec[1][2];
if(res>=7)
add+=p[pos].vec[1][0];
ans=max(ans,add+dfs(pos+1,(res+3)%10));
}
if(p[pos].num[3]){
ll add=p[pos].vec[3][0];
if(res==9)
add*=2;
ans=max(ans,add+dfs(pos+1,(res+1)%10));
}
dp[pos][res]=ans;
return ans;
}
bool cmp(ll a,ll b){return a>b;}
int main()
{
memset(dp,-1,sizeof(dp));
scanf("%d",&n);
int c;
ll v;
for(int i=1;i<=n;i++){
scanf("%d",&m);
while(m--){
scanf("%d%lld",&c,&v);
p[i].num[c]++;
p[i].vec[c].push_back(v);
}
for(int j=1;j<=3;j++)
if(p[i].num[j])
sort(p[i].vec[j].begin(),p[i].vec[j].end(),cmp);
}
printf("%lld\n",dfs(1,0));
return 0;
}