• Codeforces 607B Zuma(区间DP)


    题目大概说,有n个颜色的宝石,可以消除是回文串的连续颜色序列,问最少要几下才能全部消除。

    • 自然想到dp[i][j]表示序列i...j全部消除的最少操作数
    • 有几种消除的方式都能通过枚举k(i<=k<j)从min(dp[i][k],dp[k+1][j])转移
    • 还有一种先消除中间的,剩余两部分组成回文串再消除,这种消除方式转移不会。。想到的时间复杂度太高。。
    • 看了tourist的代码,发现神的转移好简洁,这种方式就是从dp[i+1][j-1](c[i]=c[j])转移的
    • 应该可以这么理解,如果c[i]=c[j],而序列i+1...j-1消除到最后一步必定会剩下一个回文串!然后这个回文串就和c[i]和c[j]拼在一起,一起消除!感觉好强。。
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int c[555],d[555][555];
     6 int main(){
     7     int n;
     8     scanf("%d",&n);
     9     for(int i=0; i<n; ++i){
    10         scanf("%d",c+i);
    11     }
    12     for(int i=0; i<n; ++i){
    13         d[i][i]=1;
    14         for(int j=i+1; j<n; ++j){
    15             d[i][j]=11111111;
    16         }
    17     }
    18     for(int len=2; len<=n; ++len){
    19         for(int i=0; i+len-1<n; ++i){
    20             int j=i+len-1;
    21             for(int k=i; k<j; ++k){
    22                 d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]);
    23             }
    24             if(c[i]==c[j] && len==2) d[i][j]=1;
    25             else if(c[i]==c[j]) d[i][j]=min(d[i][j],d[i+1][j-1]);
    26         }
    27     }
    28     printf("%d",d[0][n-1]);
    29     return 0;
    30 }
  • 相关阅读:
    C# 多线程并发锁模式-总结
    C# 7 out variables, tuples & other new features
    AngleSharp 的Dom 选择器
    Html Agility Pack
    javascript判断是否按回车键
    VSTS 免费代码git/tfs托管体验-使用代码云托管
    NPOI 中的公式列的值的获取
    topshelf 开发windows 服务资料
    vue之指令
    hash和md5
  • 原文地址:https://www.cnblogs.com/WABoss/p/5677074.html
Copyright © 2020-2023  润新知