• Tiling Terrace CodeForces


    Tiling Terrace

    [Time Limit: 1000 msquad Memory Limit: 262144 kB ]

    题意

    给出一个字符串 (s),每次可以选择三种类型来获得价值
    (Type1:“.”) 获得 (w_1)
    (Type2:“..”) 获得 (w_2)
    (Type3:“.#.”) 获得 (w_3)
    此外,还有两个限制条件
    (Limti1:Type1) 至多只能选 (K)
    (Limit2:) 每个字符只能被选择一次
    问最多可以获得的价值。

    思路

    首先可以发现,对于两个相邻的 (#),如果我们确定了这两个的状态,也就是不用或者当成 (Type3) 来用,那么我们就可以知道这两个 (#) 之间可用 (.) 的数量。如果这个数量是奇数,那么意味着其中有一个 (.) 拿来用作 (Type1) 是必然不会亏的,也就是这个 (.) 是白嫖的。

    (dp[i][j][k][0/1]) 表示到第 (i)(#) 号为止,白嫖了 (j)(Type1),选了 (k)(Type3),并且第 (i)(#) 是否当成 (Type3) 来用。
    为了方便计算,我们可以在整个字符串的开头加入一个 (#),整个字符串的结尾加入一个 (#),那么整个的状态必然要从 (dp[0][0][0][0]) 开始递推,必然以 (dp[#_{number}][j][k][0]) 结尾。

    这样推出来以后,我们就知道了白嫖 (a)(Type1),选 (c)(Type3) 的情况下,最多可以获得多少个 (b)。最后对 (a、b、c) 贪心求答案,尝试在 (Type1) 不超过 (K) 的情况下把 (Type2) 换成 (Type1)

    我们可以发现,由于 (#) 的个数最多就 (50) 个,那么白嫖的 (Type1) 必然不会超过 (51),所以整个 (dp) 的复杂度是 (Oleft(50^3 imes4 ight))

    /*************************************************************** 
    	> 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
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    fiddler 保存请求数据并发送到自己的服务器接口
    入门chrome插件开发教程和经验总结,一篇就搞掂!
    文件图标SVG
    银行开发平台
    银联号
    数学好玩 沛沛猜想
    Jenkins安装 maven插件
    jQuery的on绑定click和直接绑定click区别
    PC与移动端都可以使用的横向导航,可点击可滑动
    layui加载层(有文字提示版)跳出iframe父级
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/11978759.html
Copyright © 2020-2023  润新知