digit puzzle 数字谜 Uva12107
来源:互联网 发布:淘宝网上开店需要多少钱 编辑:程序博客网 时间:2024/04/28 11:34
题目
digit puzzle 数字谜 Uva12107
给一个不完整表达式,要求修改尽量少的数,使修改后的数字谜只有唯一解。空格和数字可以随意替换,但不能增删,表达式中所有涉及的数必须是没有前导零的正数。输入数字谜一定形如a*b=c,其中a、b、c分别最多有2、2、4位。用下划线表示未知数字。输入保证会有解,即有经过变换后肯定能有一个表达式有唯一解。如果有多个解,输出字典序最小的解, 下划线比数字小
输入 _*__=78 //表达式 答案不唯一 1*78=78 2*39=78 输出 _*_7=_8 //表达式唯一解 4*17=68; 右原始表达式第3个下划线和7交换1次得到tip: 7*__=_8 //表达式也有唯一解 7*14=98; 但修改次数也是1 但字典序不是最小
思路
初始状态Swhile True: 每次交换一个不同的数字或下划线 形成新的表达式S if 表达式S 有唯一解: 停止搜索,结束
1、首先要有一个逻辑 判断表达式解是否唯一
2、每次交换一个不同的数字或下划线 形成新的表达式,校验是否唯一解,不唯一重复步骤2
问题
1、如何保证修改次数最小?
IDA*深度迭代搜索
2、如何保证修改次数相同时 字典序最小?
在搜索时保证首先搜索字典序最小的状态,那么第一个搜索到的解就是答案
3、如何判断表达式解是否唯一?
初始状态Sall=0def isOk(S): if S 中没有空格: if 校验表达式==成立: all++; else for 下划线 in 所有的下换线: 替换下划线 = 0,1,2,...,9 获得新的状态S1。 递归S1#上述思路 可以优化,不过下面代码没有实现# 1\ 替换a、b中的下换线。计算c=a*b, 匹配c与表达式中c # 2\ 一旦all >=2后 就不需要查找了。肯定不是唯一解
4、如何存储表达式 (这是任何题目都避免不了的问题)
因为最多涉及8个数字或下划线 ,用4个bit存储一个数字, 正好用1个int型=32位;
因为下划线比数字小,所以空格用0=0000表示 数字用原始数字+1存储即[0001, 1010] 不存在用NAN=15=1111表示。如果数字是无符号的int型,那么数字越小对应的字典序也越小
案例验证
输入 _*__=78输出 _*_7=_8
代码
/* * 思路 * 最多涉及8个数字 用4个bit存储一个数字, 正好32位=1个int型; 空格用0=0000表示 数字用原始数字+1存储即[0001, 1010] 不存在用NAN=15=1111表示,一定是数无符号整型 * 初始状态s0 * 转移方程 s = { sj | si中8个数字或空格, 除15外 任意两个不同的值交换得到sj } * */#define MAXDEPTH 10#define NAN 15// 交换s[i]<-->s[j]#define chg(s, i, j)\do{\ int __i, __j, __k;\ for( __i=(i)*4, __j=(j)*4, __k=0; __k<4; __k++, __i++, __j++)\ {\ if ( (s&1<<__i)>>__i != (s&1<<__j)>>__j )\ {\ if ( s&1<<__i ) { s &= ~(1<<__i); s |= (1<<__j); }\ else { s &= ~(1<<__j); s |= (1<<__i); }\ }\ }\}while(0)//获取s[i]的数字#define slice(s, i) (s>>(i)*4&15)//更新s[i]的数字=v#define update(s, i, v) do{ s &= ~(15<<(i)*4); s |= (v)<<(i)*4; } while(0)int MaxDepth;int depth;int ans;static int okNum(int s, int index){ int i, k, v, a, b, c, num; num = 0; // 所有空格替换完毕 if (index==-1) { // 解析a,b,c a=b=c=0; for(i=0; i<8; i++) { // 跳过NAN if( slice(s,i) == NAN ) continue; if(i==0) { c += (slice(s,i)-1); } else if(i==1) { c += (slice(s,i)-1) * 10; } else if(i==2) { c += (slice(s,i)-1) * 100; } else if(i==3) { c += (slice(s,i)-1) * 1000; } else if(i==4) { b += (slice(s,i)-1); } else if(i==5) { b += (slice(s,i)-1) * 10; } else if(i==6) { a += (slice(s,i)-1); } else if(i==7) { a += (slice(s,i)-1) * 10; } } return a*b==c ? 1:0 ; } /* * 遇到空格0 时填充数字1,2,...,10, 保证没有前导0 * 递归到index-1 */ if( slice(s,index) == 0 ) { for(v=0; v<10; v++) { // 1、index=3 5 7时 不能为0. // 2、前一个index+1=1(值为0)或NAN(不存在)时 不能为0 if(v==0) { if( index==3 || index==5 || index==7) continue; if( slice(s,index+1)==1 || slice(s,index+1)==NAN) continue; } update(s, index, v+1); num += okNum(s, index-1); } } else { num += okNum(s, index-1); } return num;}/* 搜索第一个符合条件的答案 */static int search(int s){ int i,j, g, v, a, b, k; unsigned int tmp, sNew[28]; // 数量<=8时 任意交换两个最多7*8/2=28种可能 if (depth >= MaxDepth ) return 0; if( okNum(s, 7)==1 ) { ans = s; return 1; } // 初始化sNew 在有序集合{s|交换s中任意两个不相同的数字或空格, si<sj } g=-1; for(i=0; i<8; i++) if( slice(s, i)!=NAN ) { for(j=i+1; j<8; j++) if( slice(s, j)!=NAN ) { if(slice(s, i)==slice(s, j)) continue; tmp = s; chg(tmp, i, j); k=g; while(k>=0 && sNew[k] > tmp) { sNew[k+1]=sNew[k]; k--; } sNew[k+1]=tmp; g++; } } // 寻找需要交换的a, b 使得交换后 中最小k小 // 按照交换后字典序 曾序递归 for(i=0; i<=g; i++) { depth++; if ( search(sNew[i]) ) return 1; depth--; } return 0;}int main(){ int i,j,k,l, n, s0; char text[8+1]; scanf("%s", text); //初始化答案 ans=-1; // 初始化s0 l=-1; while(text[++l]!='\0'); s0=-1; k=0; for(i=0,j=l-1; j>=0; j--) { if( text[j] == '=' ) i = 4; else if( text[j] == '*') i = 6; else { update(s0, i, (text[j]=='_'?0:(text[j]-'0')+1)); i++; } } // printf("s0:"); // ppp(&s0, 32); // IDA*搜索 for(MaxDepth=1; MaxDepth<MAXDEPTH; MaxDepth++) if( search(s0) ) break; // 打印答案 // printf("ans:"); // ppp(&s0, 32); if( ans==-1 ) printf("no solution\n"); else { for(i=7; i>=0; i--) { if(i==5) printf("*"); if(i==3) printf("="); j = slice(ans, i); if(j==0) printf("_"); else if(j!=NAN) printf("%d", j-1); } printf("\n"); } return 0;}
阅读全文
0 0
- digit puzzle 数字谜 Uva12107
- UVa12107 - Digit Puzzle
- Digit Puzzle UVA
- Digit Puzzle UVA
- 数字谜1 C实现
- 数字谜2 C实现
- 字谜
- 字谜
- 字谜
- 微软面试题之数字谜题
- HDU 2931 Digit Puzzle 搜索 DFS
- 数数字(Digit Counting)
- 微软面试题之数字谜题方案
- 蓝桥杯之最简单的爆破-----数字谜
- 习题7-8:数字谜(dfs暴搜)
- UVa 1583 Digit Generator(数)
- UVa1225 Digit Counting 数数字
- Uva1225-Digit Counting-数数字
- 当OKR遇上SMART就像好马配好鞍
- Linux中对文件描述符的操作
- 常见http状态码
- Error: Could not find or load main class
- ubuntu16.04字体安装
- digit puzzle 数字谜 Uva12107
- hdu4897 Little Devil I(树链剖分+线段树)
- Android InputMethodManager软键盘
- 2017-09-11 LeetCode_021 Merge Two Sorted Lists
- 你不知道的javaScript【笔记】--- js隐/显式转换
- sizeof()用法汇总
- 设计模式之策略模式
- Python文件导入导出
- A child container failed during start