问题:

Akari Puzzle是日本Nikoli公司于1980创建一个逻辑迷题。该谜题是在一个由黑色和白色方块正方形网格中,按照如下规则放置灯泡:

1、 灯泡只能放在白色方块中;

2、在带有数字的黑色方块的水平和垂直方向邻接的白色方块放置灯泡,灯泡的总数量必须等于黑色方块中的数字;

3、灯泡的光线沿垂直方向和水平方向辐射,直到达到一个黑色的方形或网格的边缘,即该灯泡照亮的区域;

4、两个灯泡的不能互相照亮;

5、每个白色方形网格必须被照亮。

6、参见:http://www.nikoli.com/en/puzzles/bijutsukan/

解决方案(DFS+剪枝)

具体思路:

基本上是从第一个格子开始进行dfs搜索,自左至右,自上而下的顺序,对每个白格进行遍历,将所有情况搜索一遍。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define maxn 10
using namespace std;int n,m,b,ans;
int mp[maxn][maxn];
int vis[maxn][maxn];
int jmp[maxn][maxn];
int light[maxn][maxn];
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
bool getanswer = false;void showvis()             // 中间输出  方便debug
{int i,j;printf("\n");for(i=1; i<=n; i++){for(j=1; j<=m; j++){printf("%d",vis[i][j]);}printf("\n");}
}
bool isok(int tx,int ty)  // 判断能否放灯
{int i,j;for(i=tx-1; i>=1; i--){if(vis[i][ty]) return false;else if(mp[i][ty]) break ;}for(i=tx+1; i<=n; i++){if(vis[i][ty]) return false;else if(mp[i][ty]) break ;}for(j=ty-1; j>=1; j--){if(vis[tx][j]) return false;else if(mp[tx][j]) break ;}for(j=ty+1; j<=m; j++){if(vis[tx][j]) return false;else if(mp[tx][j]) break ;}return true ;
}
void expand(int tx,int ty)     // 扩展  将灯能照亮的地方都点亮
{int i,j;for(i=tx; i>=1; i--){if(mp[i][ty]) break ;else jmp[i][ty]=1;}for(i=tx; i<=n; i++){if(mp[i][ty]) break ;else jmp[i][ty]=1;}for(j=ty-1; j>=1; j--){if(mp[tx][j]) break ;else jmp[tx][j]=1;}for(j=ty+1; j<=m; j++){if(mp[tx][j]) break ;else jmp[tx][j]=1;}
}
bool judge()                 // 判断搜出来的情况是否合理
{int i,j,k,cnt;memset(jmp,0,sizeof(jmp));for(i=1; i<=n; i++){for(j=1; j<=m; j++){if(vis[i][j]) expand(i,j);        // 将标记了的都扩展}}for(i=1; i<=n; i++){for(j=1; j<=m; j++){if(!mp[i][j]&&!jmp[i][j]) return false ;      // 如果还有一个位置没亮的话就不行}}
//    showvis();for(i=1; i<=n; i++)              // 检测墙的周围灯的个数是否满足条件{for(j=1; j<=m; j++){if(light[i][j]==-1) continue ;cnt=0;for(k=0; k<4; k++){if(vis[i+dx[k]][j+dy[k]]) cnt++;}if(cnt!=light[i][j]) return false ;}}return true ;
}
bool midcut(int tx,int ty)        // 中间剪枝  如果有墙的周围不满足条件了 就 return false
{int i,j,k,cnt;for(i=1; i<=tx-2; i++){for(j=1; j<=m; j++){if(light[i][j]==-1) continue ;cnt=0;for(k=0; k<4; k++){if(vis[i+dx[k]][j+dy[k]]) cnt++;}if(cnt!=light[i][j]) return false ;}}i=tx-1;for(j=1; j<=ty-1; j++){if(light[i][j]==-1) continue ;cnt=0;for(k=0; k<4; k++){if(vis[i+dx[k]][j+dy[k]]) cnt++;}if(cnt!=light[i][j]) return false ;}return true ;
}
bool goodcut(int tx,int ty)     // 强剪枝   如果所搜点为墙 且其上方为黑暗的,则剪枝!
{int i,j,k,cnt;memset(jmp,0,sizeof(jmp));for(i=1; i<=tx-1; i++){for(j=1; j<=m; j++){if(vis[i][j]) expand(i,j);}}if(!jmp[tx-1][ty]) return false;return true ;
}
void dfs(int nx,int ny,int cxx)
{if(getanswer) return ;if(!midcut(nx,ny)) return ;  if(nx>=n&&ny>m||nx>n){if(judge())               // 全部搜完后判断情况是否合理{getanswer=true;}return ;}if(ny>m) dfs(nx+1,1,cxx);else if(mp[nx][ny]){if(nx>=2&&!mp[nx-1][ny]&&!goodcut(nx,ny)) return ;   // 注意前面的条件dfs(nx,ny+1,cxx);}else{dfs(nx,ny+1,cxx);if(!vis[nx][ny]&&isok(nx,ny)){vis[nx][ny]=1;dfs(nx,ny+1,cxx+1);vis[nx][ny]=0;}}
}
int main()
{int i,j,r,c,k;while(scanf("%d%d",&n,&m),n||m){scanf("%d",&b);memset(mp,0,sizeof(mp));memset(light,-1,sizeof(light));for(i=1; i<=b; i++){scanf("%d%d%d",&r,&c,&k);mp[r][c]=1;light[r][c]=k;}memset(vis,0,sizeof(vis));ans=1000000;dfs(1,1,0);if(ans<1000000) printf("%d\n",ans);else printf("No solution\n");}return 0;
}

												

算法复习-Akari Puzzle相关推荐

  1. 算法复习第四章动态规划

    算法复习第四章动态规划 动态规划 TSP问题 0-1bag 动态规划 TSP问题 0-1bag 最长公共子序列不考:

  2. 算法复习第三章分治法

    算法复习第三章分治法 循环日程表 最近点对 快速排序: 循环日程表 最近点对

  3. 算法复习第六章第七章

    算法复习第六章第七章 第六章回溯法 TSP问题 0-1bag问题 图着色问题 八皇后问题 第七章分支限界法 0-1bag问题 TSP问题 第六章回溯法 TSP问题 0-1bag问题 图着色问题 八皇后 ...

  4. 算法复习第五章贪心法

    算法复习第五章贪心法 概述 TSP 最近邻点策略 最短连接策略 图着色问题 最小生成树(Prim算法.Kruskal) 0-1bag问题 活动安排问题 多机调度 概述 TSP 最近邻点策略 最短连接策 ...

  5. 大三寒假--算法复习

    算法 复习的一些知识点 c++ 的数组初始化 fill memset c++ 的排序 c++ 的vetor 快速幂 m&1(位运算符) dfs和bfs 逆序对(使用归并算法解决) Java 的 ...

  6. 算法复习——动态规划篇之最长公共子序列问题

    算法复习--动态规划篇之最长公共子序列问题 以下内容主要参考中国大学MOOC<算法设计与分析>,墙裂推荐希望入门算法的童鞋学习! 1. 问题背景 子序列:将给定序列中零个或多个元素(如字符 ...

  7. 数据结构与算法复习:一

    算法复习第一天:论序 一.先了解几个人 ① 号目标人物 ② 号目标人物 二.数据结构的兴起和发展 1.客观世界与计算机世界的关系 2.程序设计的实质是什么 3.数据结构是随着程序设计的发展而发展的 三 ...

  8. 考研DS备考|算法复习|编程or上机准备

    23考研算法复习 一.图论相关算法 1.拓扑排序 2.最小生成树 2.1 Prim算法朴素实现 2.2 最小生成树Kruskal实现 3.最短路 3.1朴素版Dijkstra 3.2Bellman-f ...

  9. 算法复习笔记(三)分治法

    算法复习笔记(三)分治法 1.引入语 分治法划分对策: 子问题与原问题相比:问题性质一致,问题规模不同 求解一般分为三个阶段: 1.划分:直到问题足够小可以直接求解为止 2.求解: 3.合并:将子问题 ...

最新文章

  1. 正则表达式测试工具、网页版
  2. finalshell Linux 传输文件 xftp
  3. Gym101128F:Landscaping
  4. oracle11g32位安装流程_Oracle 11g服务器安装详细步骤图文详解
  5. 服务器怎么把信息发送给用户,java中怎么用tcp/ip将服务器的消息发送给多个用户...
  6. IO流 (二) ----- 文件流
  7. C++基础:C++的路径表示有哪些
  8. JavaScript 模块化简述
  9. 每日一题_JavaScript.两种方式实现网页加载后onload绑定多个函数?
  10. python整数作为条件_Python基本概念介绍
  11. Process.RedirectStandardInput
  12. 2020.7.16.h5面试题
  13. 60、弱电网络管理入门与基础技术
  14. Controller中使用swagger注解的正确姿势
  15. python将红底证件照转成蓝底
  16. 计算机屏幕暗度怎么调,电脑屏幕亮度太亮怎么调暗一点
  17. 【NDN基础】Named Data Networking 学习笔记
  18. OCR文字识别笔记总结
  19. 【Net】全球十大搜索引擎,你听过几个?
  20. Hp 通过MP卡启动、关闭电源 Hp9000小型机的方式

热门文章

  1. E - New Year Snowmen
  2. 编程题--疯狂序列----京东大数据笔试
  3. 后缀是lnk是什么文件_ink是什么文件
  4. 从首届微商博览会看2015年微商的趋势
  5. 黑鲨Android系统耗电高,安卓顶配,黑鲨2pro作为主力机使用四天,来聊聊使用感受...
  6. ESP32 Https server 错误Header fields are too long for server to interpret
  7. 再见2020,你好2021(2020年度总结)
  8. PPT模板 | 湖南农业大学汇报通用PPT模板
  9. PMP-总价合同、固定合同、工料合同对比
  10. 怎样更改计算机文件名,电脑如何批量修改文件名|批量修改文件名的几个小方法...