A. Girls Band Party (From 2019 ICPC Asia Yinchuan Regional)

嘿嘿,今天终于想起来这题了,写一写。

其实就是分组背包,分组背包的好处就在于分了组之后只需要考虑到当前组选了多少种,而不用记录每一种物品有没有选过。

那么用 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示第 i i i组,已经选了 j j j种物品,奖励为十分之 k k k的情况下最大能获得的分数。答案就是 m a x ( d p [ t o t ] [ j ] [ k ] ∗ ( 10 + k ) / 10 ) max(dp[tot][j][k] *(10 + k) / 10) max(dp[tot][j][k](10+k)/10),其中 t o t tot tot是组数。

转移就十分显然了,甚至不需要开滚动空间。
C o d e : Code : Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<random>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#define endl "\n"
#define fi first
#define se second
#define db double
#define gcd __gcd
#define pb push_back
#define mp make_pair
#define lowbit(x) (x & (-x))
#define PII  pair<int, int> 
#define all(x) x.begin(), x.end()
#define debug(x) cout << #x << " = " << x << endl
#define rep(i, a, b) for(__typeof(b) i = a; i <= (b); i++)
#define Rep(i, a, b) for(__typeof(a) i = a; i >= (b); i--)
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
template<class T> inline T qmin(T a, T b) { return a < b ? a : b; }
template<class T> inline T qmax(T a, T b) { return a > b ? a : b; }
typedef long long ll;
typedef unsigned long long ull;
const db eps = 1e-9;
const db PI = acos(-1);
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;//remember to modify it, No RE or MLE
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;

struct node{
	string name;
	int val, add;
	friend bool operator < (node p, node q){
		return p.name < q.name;
	}
}a[maxn];

int dp[maxn][6][16];
string color[maxn], bonus_name[10], bonus_color;
vector<node> G[maxn];
int n, tot;

int main()
{
	FAST;
	int T; cin >> T;
	while(T--){
		cin >> n;
		rep(i, 1, n) cin >> a[i].name >> color[i] >> a[i].val, a[i].add = 0, G[i].clear();
		rep(i, 1, 5) cin >> bonus_name[i];
		cin >> bonus_color;
		rep(i, 1, n){
			rep(j, 1, 5){
				if(a[i].name == bonus_name[j]) a[i].add += 1;
			}
			if(color[i] == bonus_color) a[i].add += 2;
		}
		sort(a + 1, a + n + 1);
		tot = 0;
		rep(i, 1, n){
			if(a[i].name != a[i-1].name) tot++;
			G[tot].pb(a[i]);
		}
		memset(dp, -1, sizeof dp);
		dp[0][0][0] = 0;
		rep(i, 1, tot){
			int len = G[i].size();
			rep(j, 0, 5){
				rep(k, 0, 15) dp[i][j][k] = dp[i-1][j][k];
			}
			rep(l, 0, len - 1){
				rep(j, 1, 5){
					rep(k, G[i][l].add, 15){
						if(dp[i-1][j-1][k-G[i][l].add] != -1) dp[i][j][k] = qmax(dp[i][j][k], dp[i-1][j-1][k-G[i][l].add] + G[i][l].val);
					}
				}
			}
		}
		int ans = 0;
		rep(j, 0, 5) rep(k, 0, 15) {
			ans = qmax(ans, dp[tot][j][k] * (10 + k) / 10);
		}
		cout << ans << endl;
	}
	return 0;
}

Over.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值