HDOJ 5004 - KAMI 神之折纸 神搜索...

56 篇文章 0 订阅

                 题意:

                          就是手机游戏KAMI...

                          有一个16*10的矩阵...每个格子里有一个数..范围是1-4...现在将一个格子点成1-4中的一个..那么与其联通的所有格子都会变成这种颜色(所谓联通就是上下左右四个方向能走到的)...现在给出了最优n(n<=8)步会让这个矩阵的所有格子都是相同的颜色...请输出任意一种方案..

                 题解:

                          明显的是搜索了...一般的思维是枚举每个联通块..然后枚举染色..这样..就算不考虑染色..枚举联通块的复杂度最高将是P(8,30)..注意是排列不是组合..因为前后顺序是有影响的...那么接下来想到的就是剪枝了..无奈姿势水平不够..怎么剪.第二个样例都跑不出来(等N久不出来)...

                          大神的方法: 这里

                          碉堡的是..只要枚举某个联通块后..再这个联通块上枚举找色顺序就可以了...也就是输出答案..在某个点不断的着n次色是一定能出最优方案的...


Program:

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h> 
#include<queue>
#include<map>
#include<algorithm>
#define MAXN 205
#define ll long long
#define oo 1e+10
#define eps 1e-10
using namespace std;    
struct node
{
      int y,x;
};
int w[4][2]={{0,1},{1,0},{0,-1},{-1,0}},ans[MAXN]; 
bool used[17][11];
char s[17][11];
queue<node> Q;
bool dfs(int i,int j,int T)
{
      int x,y,k,e,color; 
      char now[17][11];
      node h,p;
      if (!T)
      {
              for (i=1;i<=16;i++)
                 for (j=1;j<=10;j++)
                    if (s[i][j]!=s[1][1]) return false;
              return true;
      }  
      color=s[i][j]-'0';    
      for (k=1;k<=4;k++)
         if (k!=color)
         { 
                 memcpy(now,s,sizeof(s));
                 memset(used,false,sizeof(used));
                 while (!Q.empty()) Q.pop();
                 h.y=i,h.x=j;
                 used[i][j]=true;
                 Q.push(h);
                 while (Q.size())
                 {
                         h=Q.front(),Q.pop(); 
                         s[h.y][h.x]=k+'0'; 
                         for (e=0;e<4;e++)
                         {
                                 p.y=h.y+w[e][0],p.x=h.x+w[e][1];
                                 if (s[p.y][p.x]-'0'!=color) continue;
                                 if (used[p.y][p.x]) continue; 
                                 used[p.y][p.x]=true;
                                 Q.push(p);
                         }                                       
                  }
                  ans[T]=k; 
                  if (dfs(i,j,T-1)) return true;
                  memcpy(s,now,sizeof(s));   
          }     
      return false;
}
int main()
{   
      int C,cases,T,i,j,x;  
      scanf("%d",&C);
      for (cases=1;cases<=C;cases++)
      {
              scanf("%d",&T); 
              memset(s,0,sizeof(s));
              for (i=1;i<=16;i++) scanf("%s",s[i]+1); 
              printf("Case #%d:\n",cases);  
              for (i=1;i<=16;i++)
              {
                     for (j=1;j<=10;j++)
                     {
                            if (s[i-1][j]==s[i][j] || s[i][j-1]==s[i][j]) continue;
                            if (!dfs(i,j,T)) continue;
                            for (x=T;x>=1;x--) 
                                printf("%d %d %d\n",ans[x],i,j);  
                            break; 
                     }
                     if (j<=10) break;
              }
      }  
      return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值