[题解]AT_abc325_g [ABC325G] offence

思路

看到消除区间,并且 |S|300 果断选择区间 DP。

定义 dpi,j 表示操作 ij 区间能剩下最少数量。

首先枚举 i,j,然后枚举一个分解点 k,那么显然有 dpi,j=minik<j{dpi,k+dpk+1,j}

如果 sio,需要单独考虑一下。

依旧在 k(i,j] 寻找 skfk,如果 dpi+1,k1 不为 0,表明 (i+1)(k1) 不能完全操作掉,因此无法使得 i,k 挨在一起,形成 of

所以当我们找到满足 dpi+1,k1=0k 时,ik 中的所有元素都能被消除,并且可以在 k 之后顺手消除 K 个,所以直接将 dpi,j 设为 min(dpi,j,max(dpk+1,jK,0)) 即可。

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 310;  
int n,m;  
int dp[N][N];  
string s;  
  
int main(){  
    ios::sync_with_stdio(0);  
    cin.tie(0);  
    cout.tie(0);  
    cin >> s >> m;  
    n = s.size();  
    s = ' ' + s;  
    for (re int i = 1;i <= n;i++){  
        for (re int j = i;j <= n;j++) dp[i][j] = j - i + 1;  
    }  
    for (re int l = 2;l <= n;l++){  
        for (re int i = 1;i + l - 1 <= n;i++){  
            int j = i + l - 1;  
            if (l == 2){  
                if (s[i] == 'o' && s[j] == 'f') dp[i][j] = 0;  
            }  
            else{  
                for (re int k = i;k < j;k++) dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j]);  
                if (s[i] == 'o'){  
                    for (re int k = i + 1;k <= j;k++){  
                        if (s[k] == 'f' && !dp[i + 1][k - 1]) dp[i][j] = min(dp[i][j],max(dp[k + 1][j] - m,0));  
                    }  
                }  
            }  
        }  
    }  
    cout << dp[1][n];  
    return 0;  
}  

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18262946

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示