• [BZOJ1032][P1840] 祖玛 记忆化搜索 动态规划


     
      描述 Description  
      某天,小x在玩一个经典小游戏——zumo。
    zumo游戏的规则是,给你一段长度为n的连续的彩色珠子,珠子的颜色不一定完全相同,但是,如果连续相同颜色的珠子大于等于k个,这些珠子就会消失。当然,最初的状态可能不必要直接消掉一些珠子(见样例)。现在你有无穷个所有颜色的珠子,并且你可以在任意地方插入珠子。
    现在提出问题:给你一个固定的状态,你最少需要用多少个小球,才能将所有的小球消去。

         
         
      输入格式 Input Format  
      第一行是两个整数,n (1 ≤ n ≤ 100)和k(2 ≤ k ≤5),表示有n个彩色珠子,必须连续有k个以上(包括k个)相同颜色的珠子,这些珠子才会消失。
    接下来一行包含n个用空格隔开的整数,每个数在1到100之间,每个数值表示一个珠子的颜色,相同的数字意味着珠子的颜色相同。
         
         
      输出格式 Output Format  
      一个整数,表示最少需要用多少个小球,才能让所有的小球消失。
    http://www.cnblogs.com/AndreMouche/archive/2011/02/27/1966504.html
    ↑大神的程序...
     
    状态可以通过记忆化搜索找(复习时间:记忆化搜索就是把找到的东西都存在f[i][j][cnt]里下次用这个值就不用搜了... )
    f[i][j][cnt] =x 表示从i到j的珠子前有cnt个连续的紧跟在i前面的与第i个珠子相同的珠子,此时需要x个珠子可以让他们全部消失(BOOM!)
    搜索时也是这三个变量(虽然记录的是cnt,但是cnt+1才是此时记录的连续的珠子的个数(加上i位置的珠子))
     
     
     
     
    下面是手把手的贴心的和贴代码没两样的题解...聪明人就不要往下看了...(我找不到要点所以就把代码含义叙述了一遍)
     
    当f[i][j][cnt] 储存有有意义的值(搜索过了)的时候,直接返回该值;
    i=j时 返回k(k个珠子时可以可以消失)-(1+cnt)(把最后剩下来的珠子补成k个)
    i>j时,当然不需要珠子啦...返回0
     
    连续的珠子数(cnt+1)大于等于k时,则消去这些珠子,搜索从i+1到j个珠子(因为前面多于k的珠子自动消去所以此时f[i+1][j][0]和f[i][j][cnt]等效.....)
    小于时,则搜索手动加进去一个珠子的状态,即f[i][j][cnt+1]+1和f[i][j][cnt]等效...
     
    此时该搜的都搜了,,就需要dp来找状态的最优值...,在i和j之间找一个w,w位置的小球和i位置的一样......则
    f[i][j][cnt] =min(f[i][j][cnt],f[i+1][w-1][0]+f[w][j][min(cnt+1,k-1)]);
    这个应该很好理解所以我就不手把手解释了....就是消去中间的珠子然后让两边一样的珠子撞在一起再消一次,正常的祖玛方法......
     
    最后把f[i][j][cnt]的值返回
     
    有些地方我没写dfs(i,j,cnt)什么的但是不代表不用递归.....某个f[i][j][cnt]如果没值当然要搜索它啊...仙女教母不会自动给你初始化成正确答案的,这是搜索,醒醒!!!!而且搜索之后别忘了记忆化...所以这个鬼畜的东西才叫记忆化搜索...
     
    欢迎神犇捉虫...虽然神犇看这么简单的题估计题解都不愿意写...
    因为校对无能所以真的有什么错误我不负责任...
     
    代码
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 int n,k;
     9 int a[110][2]={};
    10 int dd[110]={};
    11 int f[110][110][110];
    12 int fff(int b1,int b,int cnt){
    13     int &cur=f[b1][b][cnt];
    14     if(cur!=-1) return cur;
    15     if(b1==b){
    16         cur=k-cnt-1;
    17         return cur;
    18     }
    19     if(b1>b){
    20         cur=0;
    21         return cur;
    22     }
    23     if(cnt<k-1){
    24         cur=fff(b1,b,cnt+1)+1;
    25     }
    26     else{
    27         if(cnt>=k-1){
    28             cur=fff(b1+1,b,0);
    29         }
    30     }
    31     int i;
    32     for(int i=b1+1;i<=b;i++){
    33         if(dd[i]!=dd[b1]) continue;
    34         int value=fff(b1+1,i-1,0)+fff(i,b,min(cnt+1,k-1));
    35         if(value<cur) cur=value;
    36     }
    37     return cur;
    38 }
    39 int main(){
    40     cin>>n>>k;
    41     int tail=-1;
    42     int sumn=0;
    43     for(int i=1;i<=n;i++){
    44         cin>>dd[i];
    45     }
    46     memset(f,-1,sizeof(f));
    47     cout<<fff(1,n,0)<<endl;
    48     return 0;
    49 }
    View Code
  • 相关阅读:
    高级特性(7)- 高级AWT
    洛谷 P1948 [USACO08JAN]电话线Telephone Lines
    洛谷 P2015 二叉苹果树
    洛谷 P2014 选课
    洛谷 P1560 [USACO5.2]蜗牛的旅行Snail Trails(不明原因的scanf错误)
    cogs 10. 信号无错传输
    cogs 9. 中心台站建设。。。
    洛谷 P1731 生日蛋糕
    洛谷 P1092 虫食算
    洛谷 P1034 矩形覆盖
  • 原文地址:https://www.cnblogs.com/137shoebills/p/7783643.html
Copyright © 2020-2023  润新知