[SCOI2007]压缩 题解

[SCOI2007]压缩

https://ac.nowcoder.com/acm/problem/20252

[SCOI2007]压缩 题解
很显然是一个dp。。。很妙的一个dp,很难的一个dp。。。
因为M,R存在造成的不同结果,需要分类讨论。
记:

  1. dp[i][j][0]为区间[i,j]不加M时最短长度
  2. dp[i][j][1]为区间[i,j]有M时最短长度

那么转移方程为:
dp[i][j][0]=min(dp[i][k][0]+i-k)| i<=k<=j
dp[i][j][0]=min(dp[i][j][0],dp[i][(i+j)/2][0]+1)|如果可以被压缩的话
dp[i][j][1]=min(min(dp[i][k][0],dp[i][k][1])+1+min(dp[k+1][j][0],dp[k+1][j][1])) | 枚举加入的M的位置


这个区间dp的精髓大约就是划分吧

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX_N=1e5+20;
const int INF=0x3f3f3f3f;
int dp[55][55][2];
char s[55];
int n;
bool fun(int l,int r){
    int len=r-l+1;
    if(len%2==1)return 0;
    int mid=(l+r)/2;
    for(int i=l,j=mid+1;i<=mid;i++,j++){
        if(s[i]!=s[j])return 0;
    }
    return 1;
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("square.out","w",stdout);
    scanf("%s",s+1);
    n=strlen(s+1);
    for(int i=0;i<55;i++){
        for(int j=0;j<55;j++){
            dp[i][j][0]=dp[i][j][1]=INF;
        }
    }
    for(int i=1;i<=n;i++)dp[i][i][0]=1,dp[i][i][1]=2;

    for(int len=2;len<=n;len++){
        for(int i=1;i<=n;i++){
            int l=i,r=i+len-1;
            if(r>n)continue;
            for(int k=l;k<=r;k++){
                dp[l][r][0]=min(dp[l][r][0],dp[l][k][0]+r-k);
            }
            if(fun(l,r)){
                dp[l][r][0]=min(dp[l][r][0],dp[l][(l+r)/2][0]+1);
            }
            for(int k=l;k<r;k++){
                dp[l][r][1]=min(dp[l][r][1],min(dp[l][k][0],dp[l][k][1])+1+min(dp[k+1][r][1],dp[k+1][r][0]));
            }
        }
    }
    int ans=min(dp[1][n][0],dp[1][n][1]);
    printf("%d\n",ans);
}
全部评论

相关推荐

数学转码崽:一直给我推,投了又不理,理了又秒挂
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务