• 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;
    }
  • 相关阅读:
    第一次作业
    第四次作业
    第五次作业《构建之法》心得体会
    第三次作业
    第二次作业
    第一次作业
    个人简介
    读《构建之法》有感
    第四次博客园作业(2)
    第四次博客园作业(1)
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/6366725.html
Copyright © 2020-2023  润新知