zoukankan      html  css  js  c++  java
  • 「Poetize5」水叮当的舞步

    Description

    水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变。
    为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~
    地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。
    水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。
    由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。

    题解:

    我来当搬运工。。。

    类型:IDA* (迭代加深启发式搜索)

    方法一:

    枚举每次选取了哪种颜色,然后找出左上角的格子所在的联通块,改变颜色。

    为了避免来回改变、搜索深度过大,采用迭代加深的dfs限制搜索步数。

    迭代加深也就是,依次限制搜索深度为0123……进行搜索,搜索过程中发现深度超过限制就马上退出。只要搜索成功就找到了答案,也可以立即退出。

    期望得分:0~10分。

    方法二:

    加入一个小剪枝:如果改变颜色后,左上角格子所在的联通块大小没有改变,可以剪枝。这样可以避免来回往复地搜索。

    期望得分:10~20分。

    方法三:

    采用IDA*算法,设计估价函数。可以发现如果当前矩阵中除了左上角的联通块之外,共有M种颜色,那么还需要的步数不小于M。因此如果当前搜索深度+估价函数的值>深度限制,可以回溯。

    期望得分:50~70分。

    方法四:

    我们可以发现,每次寻找左上角的格子所在的联通块耗费的时间常数巨大。因此我们在这里寻求突破。

    我们引入一个N*Nv数组。左上角的格子所在的联通块里的格子标记为1。左上角联通块周围一圈格子标记为2,其它格子标记为0。如果某次选择了颜色c,我们只需要找出标记为2并且颜色为c的格子,向四周扩展,并相应地修改v标记,就可以不断扩大标记为1的区域,最终如果所有格子标记都是1,那么显然找到了答案。

    代码:

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 500+100
     26 
     27 #define maxm 500+100
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define mod 1000000007
     44 
     45 using namespace std;
     46 
     47 inline int read()
     48 
     49 {
     50 
     51     int x=0,f=1;char ch=getchar();
     52 
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54 
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56 
     57     return x*f;
     58 
     59 }
     60 const int dx[4]={-1,0,0,1},dy[4]={0,-1,1,0};
     61 int a[9][9],v[9][9],f[6],n,ID;
     62 inline int left()
     63 {
     64     int tmp=0;
     65     memset(f,0,sizeof(f));
     66     for1(i,n)for1(j,n)
     67     if(!f[a[i][j]]&&v[i][j]!=1){f[a[i][j]]=1;tmp++;}
     68     return tmp;
     69 }
     70 inline void dfs(int x,int y,int c)
     71 {
     72     v[x][y]=1;
     73     for0(i,3)
     74     {
     75         int xx=x+dx[i],yy=y+dy[i];
     76         if(xx<1||xx>n||yy<1||yy>n||v[xx][yy]==1)continue;
     77         v[xx][yy]=2;
     78         if(a[xx][yy]==c)dfs(xx,yy,c);
     79     }
     80 }
     81 inline int fill(int c)
     82 {
     83     int tmp=0;
     84     for1(i,n)for1(j,n)
     85     if(a[i][j]==c&&v[i][j]==2)
     86     {
     87         tmp++;
     88         dfs(i,j,c);
     89     }
     90     return tmp;
     91 }
     92 inline bool IDA(int dep)
     93 {
     94     int g=left();
     95     if(dep+g>ID)return 0;
     96     if(!g)return 1;
     97     int rec[9][9];
     98     for0(i,5)
     99     {
    100         memcpy(rec,v,sizeof(v));
    101         if(fill(i)&&IDA(dep+1))return 1;
    102         memcpy(v,rec,sizeof(v));
    103     }
    104     return 0;
    105 }
    106 
    107 int main()
    108 
    109 {
    110 
    111     freopen("input.txt","r",stdin);
    112 
    113     freopen("output.txt","w",stdout);
    114 
    115     while(cin>>n&&n)
    116      {
    117          memset(a,0,sizeof(a));
    118          memset(v,0,sizeof(v));
    119          for1(i,n)for1(j,n)a[i][j]=read();
    120          dfs(1,1,a[1][1]);
    121          for(ID=0;;ID++)
    122             if(IDA(0))break;
    123          printf("%d
    ",ID);
    124     }
    125 
    126     return 0;
    127 
    128 }
    View Code
  • 相关阅读:
    CentOS 7.0安装Zimbra 8.6邮件服务器
    centos7备份还原与grub2引导和rescue模式修改root密码
    通过grub硬盘安装centos7
    CentOS系统中常用查看系统信息和日志命令小结
    安装完最小化 RHEL/CentOS 7 后需要做的 30 件事情(一)
    linux 下shell脚本执行多个命令的方法
    centos Crontab
    抓取某网站信息时遇到的问题及解决 The character set provided in ContentType is invalid. Cannot read content as string using an invalid character set
    HttpClient不必每次新建实例而RestSharp推荐新建实例的原因
    .net core读取json配置文件
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4054796.html
Copyright © 2011-2022 走看看