zoukankan      html  css  js  c++  java
  • uva 12553 Countdown (搜索+剪枝)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3998

      组队训练时候的一道题。题意是用给出的6个数利用加减乘除求出一个最接近给定数字的数,输出解决方案。

      直接用状态压缩的方法,利用集合并,在两集合得出的数值之间加入运算符,存到新的集合之中去。如果不加入剪枝,总的状态数多达50W个,STL的常数大,所以会直接超时了。然后我们可以加上这样的一个剪枝,对于同一个状态,插入的数不应该重复,因为这样的一个数我们只需要一种获取方式就够了。于是,我们就可以用set来判断是否有数值是重复出现的。这样子的剪枝,就减去了大部分的状态了,最终只剩下大约3W种状态左右,然后就能顺利通过所有数据了。

    代码如下:

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <set>
      7 
      8 using namespace std;
      9 
     10 typedef long long LL;
     11 const char *OP = "+-*/";
     12 const int N = (1 << 6) + 10;
     13 struct Node {
     14     LL sum ,v1, v2;
     15     int s1, s2, op;
     16     Node() {}
     17     Node(LL _sum, int _s1, int _s2, LL _v1, LL _v2, int _op) {
     18         sum = _sum;
     19         s1 = _s1;
     20         s2 = _s2;
     21         v1 = _v1;
     22         v2 = _v2;
     23         op = _op;
     24     }
     25 } ;
     26 vector<Node> res[N];
     27 
     28 void PRE() {
     29     LL x;
     30     for (int i = 0; i < N; i++) res[i].clear();
     31     Node tmp;
     32     for (int i = 0; i < 6; i++) {
     33         cin >> x;
     34         tmp = Node(x, 0, 0, 0ll, 0ll, -1);
     35         res[1 << i].push_back(tmp);
     36     }
     37 }
     38 
     39 void work() {
     40     int end = 1 << 6;
     41 //    int sum = 0;
     42     Node tmp;
     43     set<int> has;
     44     for (int i = 0; i < end; i++) {
     45         has.clear();
     46         for (int t = i & (i - 1); t > 0; t = i & (t - 1)) {
     47             int op = i ^ t, szt = res[t].size(), szop = res[op].size();
     48             for (int ii = 0; ii < szt; ii++) {
     49                 for (int jj = 0; jj < szop; jj++) {
     50                     tmp = Node(res[t][ii].sum + res[op][jj].sum, t, op, res[t][ii].sum, res[op][jj].sum, 0);
     51                     if (tmp.sum > 0 && has.find(tmp.sum) == has.end()) res[i].push_back(tmp), has.insert(tmp.sum);
     52                     tmp = Node(res[t][ii].sum - res[op][jj].sum, t, op, res[t][ii].sum, res[op][jj].sum, 1);
     53                     if (tmp.sum > 0 && has.find(tmp.sum) == has.end()) res[i].push_back(tmp), has.insert(tmp.sum);
     54                     tmp = Node(res[t][ii].sum * res[op][jj].sum, t, op, res[t][ii].sum, res[op][jj].sum, 2);
     55                     if (tmp.sum > 0 && has.find(tmp.sum) == has.end()) res[i].push_back(tmp), has.insert(tmp.sum);
     56                     if ((res[op][jj].sum != 0) && (res[t][ii].sum % res[op][jj].sum == 0)) {
     57                         tmp = Node(res[t][ii].sum / res[op][jj].sum, t, op, res[t][ii].sum, res[op][jj].sum, 3);
     58                         if (tmp.sum > 0 && has.find(tmp.sum) == has.end()) res[i].push_back(tmp), has.insert(tmp.sum);
     59                     }
     60                 }
     61             }
     62         }
     63 //        sum += res[i].size();
     64     }
     65 //    cout << sum << endl;
     66 }
     67 
     68 void dfs(int id, LL val) {
     69     int szid = res[id].size();
     70     for (int i = 0; i < szid; i++) {
     71         if (res[id][i].sum == val) {
     72             if (res[id][i].op == -1) return ;
     73             dfs(res[id][i].s1, res[id][i].v1);
     74             dfs(res[id][i].s2, res[id][i].v2);
     75             cout << res[id][i].v1 << ' ' << OP[res[id][i].op] << ' ' << res[id][i].v2 << " = " << val << endl;
     76             return ;
     77         }
     78     }
     79 }
     80 
     81 void print(int tar) {
     82     cout << "Target: " << tar << endl;
     83     LL mn = 0x7777777777777777ll;
     84     int end = 1 << 6, mk;
     85     for (int i = 0; i < end; i++) {
     86         int szi = res[i].size();
     87         for (int j = 0; j < szi; j++) {
     88             if (abs(mn - tar) > abs(res[i][j].sum - tar)) {
     89                 mn = res[i][j].sum;
     90                 mk = i;
     91             }
     92 //            if (i == end - 1) {
     93 //                cout << res[i][j].sum << endl;
     94 //            }
     95 //            if (res[i][j].sum == 400) {
     96 //                for (int j = 0; j < 6; j++) {
     97 //                    putchar((i & (1 << j)) != 0 ? '1' : '0');
     98 //                }
     99 //                cout << "Ahhhhhh~" << endl;
    100 //                dfs(i, res[i][j].sum);
    101 //            }
    102         }
    103     }
    104 //    for (int i = 5; i >= 0; i--) {
    105 //        putchar(mk & (1 << i) ? '1' : '0');
    106 //    }
    107 //    cout << endl;
    108     dfs(mk, mn);
    109     cout << "Best approx: " << mn << endl << endl;
    110 }
    111 
    112 int main() {
    113 //    freopen("in", "r", stdin);
    114     int T, tar;
    115     cin >> T;
    116     while (T--) {
    117         PRE();
    118         cin >> tar;
    119         work();
    120         print(tar);
    121     }
    122     return 0;
    123 }
    View Code

    ——written by Lyon

  • 相关阅读:
    【Nginx】url 带有 “https://” 双斜杠特殊处理
    【layui】tepmlet 格式化 table 数据
    于二零二零年:终章
    【Golang】练习-Web 处理 form 表单请求失败不刷新页面并保存输入的数据
    实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例)
    面向对象的进阶(item系列,__new__,__hash__,__eq__)
    面向对象阶段复习
    计算器实例
    反射
    静态方法staticmethod和类方法classmethod
  • 原文地址:https://www.cnblogs.com/LyonLys/p/uva_12553_Lyon.html
Copyright © 2011-2022 走看看