Codeforces 1176F Destroy it!

Codeforces 1176F Destroy it!

题目链接

https://codeforces.com/contest/1176/problem/F

题目大意

有一个 $n$ 回合的游戏,每回合给你 $k$ 个花费和价值分别为 $c_i$ 和 $d_i$ 的卡牌。每回合可以以任意顺序使用总花费不超过 $3$ 的卡牌,每使用十张卡片,这第十张卡片的价值会翻倍。问最大的总价值是多少。

题目分析

对于所有的回合,定义 $f[i][j]$ 为进行到 $i$ 回合,使用了 $j$ 张卡的最大价值。那么需要考虑每一回合内的情况。对于每一回合,定义 $g[i][j][k][0/1]$ 为使用了前 $i$ 个卡牌,使用了 $j$ 张卡牌,共花费了 $k$,且有没有翻倍的卡的最大取值。显然这就是一个的背包问题,直接搞就可以。之后在考虑使用 $0$ 到 $3$ 张卡牌的情况对 $f$ 进行转移,注意一定要新加入的卡牌数和原来的卡牌数加起来超过 $10$ 的时候需要使用 $g[i][j][k][1]$ ,而其余情况需要使用 $g[i][j][k][0]$。最后取最大值即可。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 2e5 + 5;

long long inf = 0x3f3f3f3f3f3f3f3f;

int n, m, t;

long long f[maxn][15];
long long g[maxn][5][5][2];

int read(){
	int x;
	scanf("%d", &x);
	return x;
}

int main(){
	int i, j, k, l, r;
	long long x, y;
	
	n = read();
	
	for(i=0;i<=n;i++){
		for(j=0;j<=10;j++){
			f[i][j] = -inf;
		}
	}
	f[0][0] = 0;
	
	for(i=1;i<=n;i++){
		m = read();
		
		for(l=0;l<=3;l++){
			for(r=0;r<=3;r++){
				g[0][l][r][0] = g[0][l][r][1] = -inf;
			}
		}
		g[0][0][0][0] = 0;
		
		for(j=1;j<=m;j++){
			x = read();
			y = read();
			for(l=0;l<=3;l++){
				for(r=0;r<=3;r++){
					g[j][l][r][0] = g[j - 1][l][r][0];
					g[j][l][r][1] = g[j - 1][l][r][1];
				}
			}
			for(l=0;l<=2;l++){
				for(r=0;r<=3-x;r++){
					g[j][l + 1][r + x][0] = max(g[j][l + 1][r + x][0], g[j - 1][l][r][0] + y);
					g[j][l + 1][r + x][1] = max(g[j][l + 1][r + x][1], max(g[j - 1][l][r][0] + 2 * y, g[j - 1][l][r][1] + y));
				}
			}
		}
		
		for(j=0;j<10;j++){
			for(k=0;k<=3;k++){
				long long maxa = -inf;
				long long maxb = -inf;
				for(l=0;l<=3;l++){
					maxa = max(maxa, g[m][k][l][0]);
					maxb = max(maxb, g[m][k][l][1]);
				}
				
				if(j + k >= 10){
					f[i][(j + k) % 10] = max(f[i][(j + k) % 10], f[i - 1][j] + maxb);
				}else{
					f[i][j + k] = max(f[i][j + k], f[i - 1][j] + maxa);
				}
			}
		}
	}
	
	long long ans = -inf;
	for(i=0;i<10;i++){
		ans = max(ans, f[n][i]);
	}
	
	printf("%lld\n", ans);
	
	return 0;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据