• CF607B Zuma 题解


    CF607B Zuma 题解

    间隙(原题面)

    • 前排声明:蒟蒻刚学oi没多久,而且是自学的,写的可能会比较累赘,望见谅。

    前置知识

    • 基础区间dp

    题意

    给一个长度为n的串,每次都可以挑选一个回文的连续字串进行消除,删除后,剩余的串将连接在一起,形成一个新的串,求把串全部删除完需要的最小次数


    分析

    可以看出每一个区间的的求解都可以分为更小的两个区间的求解

    联想到区间dp

    (dp[l][r])为左端点为l,右端点为r时的最优解

    不难推出比较套路的状态转移方程

    • (dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]).(l<=k<r))

    同时,这里还有一个区间的回文判断

    假设我们把总区间划分为两个区间

    ([1,4,5,3,4,1,3,2])([3,2])

    其中([1,4,5,3,4,1,3,2])包含一个回文部分

    此时我们只要直接将回文部分删去即可

    (dp[l][r]=dp[l+1][r-1])

    这其实是一个类似于预处理的东西(个人看法,可能有误)

    如果一个区间包含回文部分

    则先把(dp[l][r])给预处理成它不进行划分可以产生的最小值

    再去和划分成两个区间所产生的最小值进行比较

    • (if(a[l]==a[r]))
      (dp[l[[r]=dp[l+1][r-1])

    贴上丑陋的代码

    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int MAXN = 510;
    int n,a[MAXN],dp[MAXN][MAXN];
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>a[i];
    	for(int i=1;i<=n;i++){//预处理长度为1的区间
    		dp[i][i]=1;
    	}
    	for(int len=1;len<n;len++){//枚举长度
    		for(int l=1;l<=n&&l+len<=n;l++){//枚举左右断点
    		
    			int r=l+len;
    				dp[l][r]=inf;
    			if(a[l]==a[r]){//如果包含回文部分
    				if(r==l+1){//注意,这里是区间长度为2的特判
    					dp[l][r]=dp[l+1][r-1]=1;
    				}
    				else dp[l][r]=dp[l+1][r-1];
    			}
    			for(int k=l;k<r;k++){//枚举断点
    				dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
    			}
    		}
    	}
    	cout<<dp[1][n];
    } 
    

    如有错误欢迎大佬们指出QwQ

  • 相关阅读:
    构建之法读书笔记 第4章 两人合作
    ASE19 团队项目 alpha 阶段 Frontend 组 scrum9 记录
    ASE —— 第二次结对作业
    ASE —— 第一次结对作业
    高级软件工程 —— 第一周博客作业
    软工个人总结
    六月上团队项目心得
    团队项目心得
    结对编程收获
    结对作业——随机生成四则运算(Core 第7组)
  • 原文地址:https://www.cnblogs.com/xcxc82/p/13339569.html
Copyright © 2020-2023  润新知