UVA - 12107 Digit Puzzle(数字谜)(IDA*)

题意:给出一个数字谜,要求修改尽量少的数,使修改后的数字谜只有唯一解。空格和数字可以随意替换,但不能增删,数字谜中所有涉及的数必须是没有前导零的正数。输入数字谜一定形如a*b=c,其中a、b、c分别最多有2、2、4位。
分析:

1、因为输出字典序最小,所以每一位数按“*0123456789”顺序枚举。

2、如果当前要修改的数与即将被修改的数相同,则cnt不加1。

3、检查积的时候,为防超时,只枚举两个乘数,通过检查积的位数和积的已确定数字来验证。

4、遇到空格要跳过并检查返回结果。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, -1, 0, 1, -1, -1, 1, 1};
const int dc[] = {-1, 0, 1, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const double eps = 1e-15;
const int MAXN = 10 + 10;
const int MAXT = 10000 + 10;
using namespace std;
string s;
map<int, pair<int, int> > mp;//3个字符串的起始终止下标
const string ss = "*0123456789";
int maxn;
int len;
int num;
int changetodigit(string t){
    int l = t.size();
    int ans = 0;
    for(int i = 0; i < l; ++i){
        ans = ans * 10 + t[i] - '0';
    }
    return ans;
}
bool check(){//检查积是否合法
    int x = changetodigit(s.substr(mp[0].first, mp[0].second - mp[0].first + 1));
    int y = changetodigit(s.substr(mp[1].first, mp[1].second - mp[1].first + 1));
    char str[5];
    sprintf(str, "%d", x * y);
    int l = strlen(str);
    if(mp[2].second - mp[2].first + 1 != l) return false;//位数不相同
    for(int i = mp[2].first; i <= mp[2].second; ++i){
        if(s[i] == '*') continue;
        if(s[i] != str[i - mp[2].first]) return false;
    }
    return true;
}
bool leadingzero(int cur){//判断当前下标是否为数字的第一位
    for(int i = 0; i < 3; ++i){
        if(mp[i].first == cur) return true;
    }
    return false;
}
void judge(int cur){
    if(num > 1) return;
    if(cur == mp[1].second + 1){
        if(check()) ++num;
        return;
    }
    if(s[cur] != '*') judge(cur + 1);
    else{
        for(int i = 1; i < 11; ++i){
            if(i == 1 && leadingzero(cur)) continue;
            s[cur] = ss[i];
            judge(cur + 1);
            s[cur] = '*';
        }
    }
}
bool dfs(int cnt, int cur){
    if(cnt >= maxn){
        string tmp = s;
        num = 0;
        judge(0);
        s = tmp;
        if(num == 1){
            return true;
        }
        return false;
    }
    if(cur == len) return false;
    if(s[cur] == ' '){
        if(dfs(cnt, cur + 1)) return true;
        return false;
    }
    else{
        char c = s[cur];
        for(int i = 0; i < 11; ++i){
            if(i == 1 && leadingzero(cur)) continue;
            if(c == ss[i]){//如果当前要修改的数与即将被修改的数相同
                if(dfs(cnt, cur + 1)) return true;
            }
            else{
                s[cur] = ss[i];
                if(dfs(cnt + 1, cur + 1)) return true;
                s[cur] = c;
            }
        }
        return false;
    }
}
int main(){
    int kase = 0;
    while(getline(cin, s)){
        if(s[0] == '0') return 0;
        len = s.size();
        int cnt = 0;
        int st = 0;
        for(int i = 0; i < len; ++i){
            if(s[i] == ' '){
                mp[cnt++] = pair<int, int>(st, i - 1);
                st = i + 1;
            }
        }
        mp[cnt++] = pair<int, int>(st, len - 1);
        printf("Case %d: ", ++kase);
        for(maxn = 0; ; ++maxn){
            if(dfs(0, 0)){
                printf("%s\n", s.c_str());
                break;
            }
        }
    }
    return 0;
}

 

posted @ 2017-02-05 00:03  Somnuspoppy  阅读(657)  评论(0编辑  收藏  举报