简单数谜 (caioj1044)
来源:互联网 发布:win7旗舰版打不开软件 编辑:程序博客网 时间:2024/05/24 06:39
题目见:http://www.caioj.cn/problem.php?id=1044
不想写具体思路,其实就是按行搜索逐渐往下,直至所有n*m个格子都放置了合适的数。搜时适时加必要的剪枝。
/*caioj.1044
很多人都曾经听说过数独,但你是否听说过数谜(Karuro)呢?实际上,数谜是数独的更大(且更难)
的兄弟问题,而且在日本也是非常受欢迎的。数谜问题和填字游戏类似,不过它要填的不是文字而是数
字。数谜游戏的目标是用1-9填满所有空格,且这些数字相加的和满足相应的要求(或者称为“提示”)
,且在同一栏(“栏”是指一些水平或者竖直的连续的空格,用于提示的格子不算空格)不能填重复的
数字。当所有格子按要求被填满后,这个数谜就看作被解决了。图1和图2是一个可能的数谜游戏示例。
*/
/*caioj.1044 很多人都曾经听说过数独,但你是否听说过数谜(Karuro)呢?实际上,数谜是数独的更大(且更难) 的兄弟问题,而且在日本也是非常受欢迎的。数谜问题和填字游戏类似,不过它要填的不是文字而是数 字。数谜游戏的目标是用1-9填满所有空格,且这些数字相加的和满足相应的要求(或者称为“提示”) ,且在同一栏(“栏”是指一些水平或者竖直的连续的空格,用于提示的格子不算空格)不能填重复的 数字。当所有格子按要求被填满后,这个数谜就看作被解决了。图1和图2是一个可能的数谜游戏示例。 */#include<iostream>#include<cstdio>#include<cstring>using namespace std;int t,n,m,ansx;int H[12],L[12];//存每一行的要求和值和列值 int hz[12],lz[12];//记录每一行的实时和值与没一列的实时列值 int ans[15][15],map[15][15]; //ans存储第一个答案地图,zt存搜索过程中的实时地图 bool h[15][15],l[15][15]; //一行内1-9或列内1-9是否用过 void initRead(){scanf("%d%d",&n,&m);ansx = 0;memset(ans,0,sizeof(ans));memset(h,false,sizeof(h));memset(l,false,sizeof(l));memset(hz,0,sizeof(hz));memset(lz,0,sizeof(lz));memset(map,0,sizeof(map));for(int i = 1; i<= n; i++) scanf("%d",&H[i]);for(int i = 1; i<= m; i++) scanf("%d",&L[i]);for(int i = 1; i<= n; i++){for(int j = 1;j<= m; j++){scanf("%d",&map[i][j]);h[i][map[i][j]] = true; //第i行已用掉map[i][j] ;l[j][map[i][j]] = true; //第j列已用掉map[i][j];hz[i] += map[i][j]; //第i行和值累加map[i][j] lz[j] += map[i][j]; //第j行和值累加map[i][j]; }}}void dfs(int x,int y){if(ansx >1) return; //有多于等于2个答案时不用继续,因为不用对更多的答案计数或输出。if(x > n){bool flag = true;//因为是一行行满足行值和的前提下开始下一行的搜索的。//因此在每行能填完,当填到第n+1行时只需判断列上是否满足列值和值是指定值 for(int i = 1;i<= m ;i++) if(lz[i] != L[i]) { flag = false;break;}if(flag){ansx++;if(ansx==1){ //如果是第一个方案,就记下正解 for(int i = 1;i<= n; i++){for(int j = 1;j<=m ; j++){ans[i][j] = map[i][j]; }} } }}else if(y > m){ //一行填完 时 if(hz[x] == H[x]) dfs(x+1,1);} else if(map[x][y] != 0) dfs(x,y+1); //如果当前搜到的点有值,则搜本行下一个else{for(int i = 1;i<= 9 ;i++){//如果该数在第x行和第y列没有被用过且放入i后不会超过行和值和列和值 if(!h[x][i] && !l[y][i] && hz[x]+i<=H[x] && lz[y]+i<= L[y]) {h[x][i] = true; //标记i该数在第x行已用 l[y][i] = true; //标记i该数在第y行已用 map[x][y] = i; //记入地图 hz[x] += i; //行的现有数据的和 +ilz[y] += i; //列的现有数据的和 +idfs(x,y+1);h[x][i] = false; //标记i该数在第x行未用 l[y][i] = false; //标记i该数在第y行未用 map[x][y] = 0; //从地图中清除 hz[x] -= i; //行的现有数据的和 lz[y] -= i; //列的现有数据的和}}} }int main(){freopen("1044.in","r",stdin) ;freopen("1044.out","w",stdout);scanf("%d",&t);while(t--){initRead();dfs(1,1);if(ansx == 1) {for(int i = 1;i<= n;i++){for(int j = 1;j< m;j++){printf("%d ",ans[i][j]);} printf("%d\n",ans[i][m]);}}else if(ansx > 1) printf("Not unique.\n");else printf("No answer.\n");}return 0;}
阅读全文
0 0
- 简单数谜 (caioj1044)
- 欢乐数(简单)
- 数塔(简单DP)
- EOJ 3290 找数(III) (模拟+简单数字串)
- 简单的stirling数(实验)
- 简单的stirling数(区别)
- 简单的stirling数(联系)
- 简单的stirling数(扩展)
- HDU -- 2084 数塔(简单DP)
- POJ 3176 DP(简单数塔)
- 组合数简单求法(数论)
- hdu2084 数塔(简单DP)
- 【HDU】-2084-数塔(简单DP)
- (简单DP)HDU 2084 数塔
- 最少步数(简单广搜)
- (POJ2676)Sudoku <简单数独问题>
- 完全平方数(简单的数论)
- 简单dp,hdoj2084(数塔)
- qt5.8 中文乱码
- 111. Minimum Depth of Binary Tree
- template.js
- STM32串口打印printf发送中文乱码问题
- Java 中的两种查找算法方式
- 简单数谜 (caioj1044)
- DateTimePicker控件CustomFormat格式字符串及其说明
- tabLayout改变下划线的宽度
- python 解决数组赋值问题
- 第15周项目2
- APK 混淆文章推荐
- 彻底征服 Spring AOP 之 实战篇
- 设置分屏
- C++基础——用C++实例理解UML类图