中等偏简单的一道搜索题,用状态压缩可以直接计算出来。因为mobile的一条rod只有两端,所以我们只要考虑两边分别是放置哪个/哪些重物就可以了。这个可以用集合的形式来表示,然后就是一个子集分割,但是这里不允许空集,所以初始集合有所不同。sample真实神奇,我的mobile的力矩公式都用反了居然还可以过了sample。然后换过来了以后,又发现坐标偏移的调整写错了。错了几次,终于A了。- -
代码如下:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <iostream> 6 7 using namespace std; 8 9 typedef vector<int> VI; 10 typedef pair<int, int> PII; 11 typedef vector<PII> VPII; 12 typedef pair<double, double> PDD; 13 typedef vector<PDD> VPDD; 14 15 #define PB push_back 16 #define MPR make_pair 17 #define FI first 18 #define SE second 19 #define REP(i, n) for (int i = 0; i < (n); i++) 20 const int N = (1 << 6) + 10; 21 const double eps = 1e-10; 22 VPDD rec[N]; 23 double ttWt[N], wt[10]; 24 25 int main() { 26 // freopen("in", "r", stdin); 27 // freopen("out", "w", stdout); 28 int T, n, x; 29 double res; 30 cin >> T; 31 while (T-- && cin >> res) { 32 cin >> n; 33 REP(i, 1 << n) rec[i].clear(); 34 REP(i, n) { 35 cin >> wt[i]; 36 rec[1 << i].PB(MPR(0.0, 0.0)); 37 } 38 REP(i, 1 << n) { 39 ttWt[i] = 0.0; 40 REP(j, n) { 41 if (i & (1 << j)) ttWt[i] += wt[j]; 42 } 43 // cout << i << "= =" << ttWt[i] << endl; 44 for (int t = (i - 1) & i; t > 0; t = (t - 1) & i) { 45 int op = t ^ i; 46 // cout << i << ' ' << t << ' ' << op << endl; 47 int sz1 = rec[t].size(), sz2 = rec[op].size(); 48 double cl = ttWt[op] / ttWt[i], cr = ttWt[t] / ttWt[i]; 49 REP(ii, sz1) { 50 REP(jj, sz2) { 51 double l1 = rec[t][ii].FI, r1 = rec[t][ii].SE, l2 = rec[op][jj].FI, r2 = rec[op][jj].SE; 52 rec[i].PB(MPR(max(l1 + cl, l2 - cr), max(r1 - cl, r2 + cr))); 53 // REP(j, n) cout << ((t & (1 << j)) != 0); 54 // cout << ' '; 55 // REP(j, n) cout << ((op & (1 << j)) != 0); 56 // cout << ' '; 57 // cout << ttWt[t] << ' ' << ttWt[op]; 58 // cout << "= =" << max(l1 + cl, l2 - 1.0) << ' ' << max(r1 - 1.0, r2 + cr) << endl; 59 } 60 } 61 } 62 } 63 int fullSet = (1 << n) - 1, sz = rec[fullSet].size(); 64 double mx = -1.0; 65 // cout << sz << endl; 66 REP(i, sz) { 67 if (rec[fullSet][i].FI + rec[fullSet][i].SE + eps < res) mx = max(mx, rec[fullSet][i].FI + rec[fullSet][i].SE); 68 // cout << rec[fullSet][i].FI + rec[fullSet][i].SE << endl; 69 } 70 printf("%.16f\n", mx); 71 } 72 return 0; 73 }
——written by Lyon