Codeforces 1176F
生活随笔
收集整理的這篇文章主要介紹了
Codeforces 1176F
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Codeforces 1176F
題目
題意:T組物品,按順序選一個一個選,物品首先要滿足組間的相對順序,每個物品有價值和體積,每組選擇的體積不能超過3,組內的選擇物品的順序可以調整,在總的物品的順序中,如果某一個物品它的編號是10的倍數,則這個物品的價值會翻倍。求最大價值。
做法:首先背包求出每一組,取j個物品構成體積k的最大價值,以及取j個物品構成體積k的且有一個價值翻倍的最大價值。在dp求 f[i][z] 表示前i組取了的總物品數 mod 10 是 z 的最大價值,轉移時,分跨過0,和不跨過0兩種討論即可。。。做法比較容易想到。。。然而dp邊界卡死了。。。寫起來各種問題。。。水平低啊。。。記一下這個題。以后注意了。。
#include <bits/stdc++.h>using namespace std;#define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define pb push_back #define Pii pair<int,int>typedef long double db; typedef long long ll;template<class T> inline void ckmx(T &a, T b) { if(b > a) a = b; }const int N = 200010; const int Mod = 998244353;int n, a[N]; ll b[N]; ll A[N][4][4]; // A[i][j][k] 第 i 組選 j 個物品構成體積 k 的最大價值 ll g[N][4][4][2]; // g[i][j][k][0/1] 前 i 個物品, 選 j 個物品,構成體積 k,是否有一個物品價值翻倍的最大價值 ll MX[N][4][4]; // MX[i][j][k] 第 i 組選 j 個物品構成體積 k 且有一個元素價值翻倍的最大價值 ll f[N][10]; //f[i][z] 前 i 組一共用X個物品, z = X%10int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);ll ans = 0;int T; cin >> T;rep(ti, 1, T) {cin >> n;rep(i,1,n) cin >> a[i] >> b[i];auto cal = [&](ll A[4][4]) {rep(i,0,3)rep(j,0,3) A[i][j] = -1;A[0][0] = 0;rep(i,1,n) per(j,3,1) per(k,3,a[i]) if(A[j-1][k-a[i]] != -1) {ckmx(A[j][k], A[j-1][k-a[i]] + b[i]);}};cal(A[ti]);auto cal2 = [&](ll A[4][4]) {rep(i,0,3)rep(j,0,3) A[i][j] = -1;rep(i,0,n) rep(j,0,3) rep(k,0,3) g[i][j][k][0] = g[i][j][k][1] = -1;g[0][0][0][1] = 0;g[0][0][0][0] = 0;rep(i,1,n) {rep(j,0,3) rep(k,0,3) {g[i][j][k][0] = g[i-1][j][k][0];g[i][j][k][1] = g[i-1][j][k][1];if( j>=1 && k >= a[i] ) {if(g[i-1][j-1][k-a[i]][0] != -1) ckmx(g[i][j][k][0], g[i-1][j-1][k-a[i]][0] + b[i]);if(g[i-1][j-1][k-a[i]][1] != -1) ckmx(g[i][j][k][1], g[i-1][j-1][k-a[i]][1] + b[i]);if(g[i-1][j-1][k-a[i]][0] != -1) ckmx(g[i][j][k][1], g[i-1][j-1][k-a[i]][0] + b[i] + b[i]);}}}rep(i,0,3)rep(j,0,3) A[i][j] = g[n][i][j][1];};cal2(MX[ti]);}function<int(int,int)> thz = [&](int st,int ed) -> int {int f = 0;rep(i,1,10) {if((st+i)%10 == 0) f = 1;if((st+i)%10 == ed) {if(f) return 1;}}return 0;};rep(i,0,n)rep(j,0,9) f[i][j] = -1;f[0][0] = 0;rep(i,1,T) rep(z,0,9) {f[i][z] = f[i-1][z];rep(j,1,3)rep(k,1,3) {if(f[i-1][(z-j+10)%10] == -1) continue;if(A[i][j][k] != -1 && !thz((z-j+10)%10,z)) ckmx(f[i][z], f[i-1][(z-j+10)%10] + A[i][j][k]);else if(MX[i][j][k] != -1 && thz((z-j+10)%10,z)) ckmx(f[i][z], f[i-1][(z-j+10)%10] + MX[i][j][k]);}ans = max(ans, f[i][z]);}cout << ans << endl; }轉載于:https://www.cnblogs.com/RRRR-wys/p/11008997.html
總結
以上是生活随笔為你收集整理的Codeforces 1176F的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超长情侣网名 超长情侣网名精选
- 下一篇: 简单多边形三角化(暴力)