• UVa12107


    哎呀,好久没更新了,今天来一篇吧!

    UVa12107数字谜

    题意:

    给出数字谜,要求修改尽量少的数,使得修改后的数字谜有唯一的解。

    修改指的是随意替换,空格与数字、数字与数字都可以互相替换,但涉及的数必须是没有前导零的正数,输出是修改后的数字谜。

    (建议看英文原题,这道题的英文原题比较好读懂)

    思路:

    通过观察,发现求出尽量少的数,所以采用迭代加深搜索,而且数字谜的大小并不大,所以暴力枚举能过,

    由于要求出唯一的解,所以我们应该先迭代加深搜索数字谜,然后再dfs解出来,这样就行了,我想估计我的想法不够

    简单,所以时间为2650ms,不过能够过。

    下面是代码:

    // UVa 12107
    // IDA* + 剪枝 
    #include <cstdio> 
    #include <cstring>
    using namespace std; 
    
    const char alpha[] = { '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
    
    int c1, c2, c3, cnt, maxd; 
    char str[20], ans[20];
    
    bool Vis() { 
      if (str[0] == '0' || str[c1] == '0' || str[c2] == '0') return false; 
      if (str[c1-1] != '*' && str[c2-1] != '*' && str[c3-1] != '*') {
        int a = str[c1-1] - '0', b = str[c2-1] - '0', c = str[c3-1] - '0';  
        return (a*b) % 10 == c; 
      }
      return true;     
    }
    
    bool Vis1() {
      int a = 0, b = 0, c = 0;  
      for (int i = 0; i < c1; ++i) 
        a = a * 10 + str[i] - '0'; 
      for (int i = c1; i < c2; ++i) 
        b = b * 10 + str[i] - '0'; 
      for (int i = c2; i < c3; ++i) 
        c = c * 10 + str[i] - '0'; 
      return a * b == c;     
    } 
    
    void dfs1(int from) {
      int i;
      for (i = from; i < strlen(str); ++i) if (str[i] == '*') break; 
      if (i == c3) {  
        if (Vis1()) ++cnt; 
        return;
      }
      for (int j = 1; j < 11; ++j) {
        char rem[20]; 
        memcpy(rem, str, sizeof(rem)); 
        str[i] = alpha[j];  
        if (Vis()) dfs1(i+1);   
        if (cnt > 1) return;  
        memcpy(str, rem, sizeof(rem));
      }
    }
    
    bool better() {
      for (int i = 0; i < c3; ++i) if (str[i] != ans[i]) {
        return ans[i] == ' ' || str[i] < ans[i]; 
      }
      return false; 
    } 
    
    bool dfs(int d, int from) { 
      if (d == maxd) { 
        cnt = 0;      
        memcpy(ans, str, sizeof(ans)); 
        if (Vis()) dfs1(0); 
        return cnt == 1; 
      } 
      if (from == c3) return false; 
      for (int j = 0; j < 11; ++j) {   
        char rem[20];  
        if (str[from] == alpha[j]) {
          memcpy(rem, str, sizeof(rem)); 
          if (dfs(d, from+1)) return true;  
          memcpy(str, rem, sizeof(rem));
        }
        if (str[from] != alpha[j]) {
          memcpy(rem, str, sizeof(rem)); 
          str[from] = alpha[j];
          if (dfs(d+1, from+1)) return true; 
          memcpy(str, rem, sizeof(rem)); 
        }
      }
      return false; 
    }
    
    int main() {    
      int kase = 0; 
      char a[10], b[10], c[10]; 
      while (scanf("%s", a) == 1 && a[0] != '0') {
        scanf("%s%s", b, c);
        c1 = strlen(a), c2 = strlen(a) + strlen(b), c3 = strlen(a) + strlen(b) + strlen(c); 
        memcpy(str, a, sizeof(a)); 
        strcat(str, b), strcat(str, c);
        for (int i = 0; i < c3; ++i) ans[i] = ' '; 
        char rem[20];
        memcpy(rem, str, sizeof(rem));  
        for (maxd = 0; ; ++maxd) {
          Set.clear(); 
          if (dfs(0, 0)) break;  
          memcpy(str, rem, sizeof(str)); 
        }
        printf("Case %d: ", ++kase);
        for (int i = 0; i < c1; ++i) printf("%c", ans[i]);
        printf(" ");
        for (int i = c1; i < c2; ++i) printf("%c", ans[i]);
        printf(" ");
        for (int i = c2; i < c3; ++i) printf("%c", ans[i]); 
        printf("
    ");  
      }
      return 0;
    }

    看了看时间并不是很占优势,所以接下来我会再发布一篇博客,所以说120ms左右的代码。

  • 相关阅读:
    sql删除注意的问题
    lua创建文件
    linux部分常用命令
    已知账户和密码进行远程桌面
    excel2013超链接进不去,提示“您的组织策略不允许...”
    2019-2020-1 20199321《Linux内核原理与分析》第七周作业
    《深入理解计算机系统》第一章读书笔记 20199321
    《文献管理与信息分析》速读笔记
    《深入理解计算机系统》速读笔记
    《构建之法现代软件工程》速读笔记
  • 原文地址:https://www.cnblogs.com/yifeiWa/p/11134463.html
Copyright © 2020-2023  润新知