zoukankan      html  css  js  c++  java
  • 【YBTOJ】【数位DP】擦除序列

    擦除序列

    给你一个由字母构成的字符串 (S) 。每一步都要擦除其中一个子序列,但要求被擦除的子序列必须是一个回文词。求擦除整个字符串的最少步数。
    比如,将 ( exttt{abcba})( exttt{abyczbea}) 擦除,就是合理的一步。

    (nleq16).

    题解

    没想到状压DP还可以这么用……

    设状态表示每一位是否被擦去,对于每一个状态,枚举其子集并判断子集是不是回文串。

    (但是因为智障错误调了快一个点……)

    代码

    #include <bits/stdc++.h>
    #define fo(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    const int INF = 0x3f3f3f3f,N = 20,M = 1e5+5;
    typedef long long ll;
    typedef unsigned long long ull;
    inline ll read(){
    	ll ret=0;char ch=' ',c=getchar(); 
    	while(!(c>='0'&&c<='9'))ch=c,c=getchar();
    	while(c>='0'&&c<='9')ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
    	return ch=='-'?-ret:ret;
    }
    int n;
    char a[N];
    ll dp[M];
    bool flg[M];
    signed main(){
    	memset(dp,0x3f,sizeof(dp));
    	scanf("%s",a+1);
    	n = strlen(a+1);
    	dp[0] = 0;
    	for(int i = 1 ; i < 1<<n ; i ++){
    		char ch[N]; int cnt = 0;
    		for(int j = 1 ; j <= n ; j ++)
    			if(i & (1<<(j-1)))
    				ch[++cnt] = a[j];
    		flg[i] = 1;
    		for(int j = 1 ; j <= (cnt+1)>>1 ; j ++)
    			if(ch[j] != ch[cnt-j+1]) {flg[i] = 0;break;}
    	}
    	for(int i = 1 ; i < 1<<n ; i ++)	
    		for(int j = i ; j ; j = (j-1) & i)
    			if(flg[j])
    				dp[i] = min(dp[i],dp[i^j] + 1);
    	printf("%lld",dp[(1<<n)-1]);
    }
    
  • 相关阅读:
    HSV 武胜
    crystalReportViewer+ReceiveCrystalReport.rpt+DataSet.xsd做报表 转 武胜
    Apache Gzip设置
    Linux gsoap 访问Jira
    搜索引擎Senna
    c 条件编译 ifndef解决 gcc multiple define error.
    搜索引擎 apachesolr
    Lucene:基于Java的全文检索引擎简介
    搜索引擎Zend_lucene
    基于应用程序级的Apache认证配置(普通认证篇)
  • 原文地址:https://www.cnblogs.com/Shinomiya/p/15269720.html
Copyright © 2011-2022 走看看