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

原文地址:https://www.cnblogs.com/LyonLys/p/uva_12553_Lyon.html