タイルテラスCodeForces - 1252J(DP、貪欲)

タイルテラス

\ [制限時間:1000ミリ秒\クアッドメモリ制限:262144キロバイト\]

問題の意味

文字列が与えられ\(S \)、3種類のそれぞれが値を得るように選択することができます
:\(\ ""のType1 ) 入手するには、\(W_1 \)要素
:\( ".." \タイプ2 ) 取得する(\ W_2 \)
\(タイプ3: ".. \ #" \) 取得するために\(w_3 \)元の
2つの制約があり、ほかに
\(Limti1:タイプ1 \)最大でのみ選択\(K \)
\( LIMIT2:\)の各文字のみを選択することができますが、一度
に得ることができる最大値を求めました。

思考

まず第一には、のために見つけることができる2つの隣接した\(\#\)私たちがいないこの2つの状態を、特定された場合として、または\(タイプ3は、\)を使用し、その後、私たちが知ることができる2 \( #\)\(\。\)番号。この数が奇数の場合、それはそれらの1つを意味\(。\)として使用するために使用し(タイプ1 \)\必ずしも損失ではない、つまり、\(。\)白い娼婦です。

オーダー\(DP [I] [J ] [K] [0/1] \) セクションを表す\(I \) A (\ \#\)白色売春婦の数まで\(J \)\(タイプ1 \)から選択される\(K \)\(タイプ3 \) 及び第一\(I \) A (\ \#\)かどうかのような\(タイプ3 \)の使用。
計算を容易にするために、我々は、全体の文字列の先頭に追加することができる(\#\)\、追加する文字列全体の末尾(\ \#\)をから、次いで、必要全体の状態(DP [0] \ [0 ] [0] [0] \)に結合し、再帰始まる\(DP [\ #_ {数 }] [j] [k]が[0] \) の端部に。

この打ち上げの後、我々は白い娼婦知ってます\(\)\(タイプ1 \)を選択し、(C \)\ \(タイプ3 \)数まで取得することができ、の場合には\(B \) 最後に、\(、B、C \ ) 貪欲なシークの答え、してみてください(タイプ1 \)\超えていない(K \)\の場合には\(タイプ2 \)\(タイプ1 \)

我々はそれを見ることができるので、\(\#\)それまでの数まで\(50 \) その後数ヶ月、売春の白い\(タイプ1 \)以下でなければなりません\(51 \) 全体ので\(DP \)の複雑さがある\(O \左(50 ^ 3 \ times4 \右)\) の

/*************************************************************** 
    > File Name     : J.cpp
    > Author        : Jiaaaaaaaqi
    > Created Time  : Tue 05 Nov 2019 10:00:31 PM CST
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

ll g1, g2, g3;
char s[maxn];
ll dp[60][60][60][2];
vector<int> vv;

ll calc(ll a, ll b, ll c) {
    if(a > m)   a = m;
    ll ans = a*g1 + c*g3;
    ll tmp = min(b, (m-a)/2);
    ll res = max(b*g2, (b-tmp)*g2 + tmp*2ll*g1);
    if(a+tmp*2<m && b-tmp>0)    res = max(res, res-g2+g1);
    return ans+res;
}

int main() {
    // freopen("in", "r", stdin);
    scanf("%d%d%lld%lld%lld", &n, &m, &g1, &g2, &g3);   
    scanf("%s", s+1);
    vv.clear();
    vv.pb(0);
    for(int i=1; i<=n; i++) {
        if(s[i]=='#')   vv.pb(i);
    }
    vv.pb(n+1);
    for(int i=0; i<60; i++) for(int j=0; j<60; j++)
        for(int k=0; k<60; k++) for(int z=0; z<2; z++)
            dp[i][j][k][z] = -INF;
    dp[0][0][0][0] = 0;
    int sz = vv.size()-1;
    for(int i=0; i<sz; i++) {
        int s = vv[i+1]-vv[i]-1;
        for(int j=0; j<60; j++) {
            for(int k=0; k<60; k++) {
                if(dp[i][j][k][0] >= 0) {
                    if(s>=0) dp[i+1][j+s%2][k][0] = max(dp[i+1][j+s%2][k][0], dp[i][j][k][0] + s/2);
                    if(s>=1) dp[i+1][j+(s-1)%2][k][1] = max(dp[i+1][j+(s-1)%2][k][1], dp[i][j][k][0] + (s-1)/2);
                }
                if(dp[i][j][k][1] >= 0) {
                    if(s>=1) dp[i+1][j+(s-1)%2][k+1][0] = max(dp[i+1][j+(s-1)%2][k+1][0], dp[i][j][k][1] + (s-1)/2);
                    if(s>=2) dp[i+1][j+(s-2)%2][k+1][1] = max(dp[i+1][j+(s-2)%2][k+1][1], dp[i][j][k][1] + (s-2)/2);
                }
            }
        }
    }
    ll ans = 0;
    for(int i=0; i<60; i++) for(int j=0; j<60; j++) if(dp[sz][i][j][0]>=0)  
        ans = max(ans, calc(i, dp[sz][i][j][0], j));
    printf("%lld\n", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/Jiaaaaaaaqi/p/11978759.html