• UVa 1354 枚举子集 Mobile Computing


    只要枚举左右两个子天平砝码的集合,我们就能算出左右两个悬挂点到根悬挂点的距离。

    但是题中要求找尽量宽的天平但是不能超过房间的宽度,想不到要怎样记录结果。

    参考别人代码,用了一个结构体的vector,保存每个集合合法方案的左右两端最长的距离。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 #include <map>
     6 #include <cmath>
     7 #define MP make_pair
     8 #define Ft first
     9 #define Sd second
    10 using namespace std;
    11 
    12 typedef pair<double, double> PDD;
    13 
    14 const int maxn = 10;
    15 const int maxs = 1000;
    16 
    17 vector<PDD> tree[maxs];
    18 
    19 int n;
    20 double r;
    21 double a[maxn], w[maxs];
    22 bool vis[maxs];
    23 
    24 int bitcount(int x)
    25 {
    26     int ans = 0;
    27     while(x) { ans += (x & 1); x >>= 1; }
    28     return ans;
    29 }
    30 
    31 void dfs(int S)
    32 {
    33     if(vis[S]) return ;
    34     vis[S] = true;
    35     if(bitcount(S) == 1) { tree[S].push_back(MP(0, 0)); return ; }
    36 
    37     PDD t = MP(0, 0);
    38     for(int s1 = (S-1)&S; s1; s1 = (s1-1)&S)
    39     {
    40         int s2 = S ^ s1;
    41         dfs(s1); dfs(s2);
    42         double x1 = w[s2] / w[S], x2 = w[s1] / w[S];
    43         for(int i = 0; i < tree[s1].size(); i++)
    44             for(int j = 0; j < tree[s2].size(); j++)
    45             {
    46                 t.Ft = max(x1 + tree[s1][i].Ft, tree[s2][j].Ft - x2);
    47                 t.Sd = max(x2 + tree[s2][j].Sd, tree[s1][i].Sd - x1);
    48                 if(t.Ft + t.Sd < r) tree[S].push_back(t);
    49             }
    50     }
    51 }
    52 
    53 int main()
    54 {
    55     int T; scanf("%d", &T);
    56     while(T--)
    57     {
    58         scanf("%lf%d", &r, &n);
    59         for(int i = 0; i < n; i++) scanf("%lf", a + i);
    60         int all = (1 << n) - 1;
    61 
    62         for(int i = 0; i <= all; i++)
    63         {
    64             w[i] = 0;
    65             tree[i].clear();
    66             for(int j = 0; j < n; j++) if(i & (1 << j))
    67                 w[i] += a[j];
    68         }
    69 
    70         memset(vis, false, sizeof(vis));
    71         dfs(all);
    72         double ans = -1;
    73         for(int i = 0; i < tree[all].size(); i++) ans = max(ans, tree[all][i].Ft + tree[all][i].Sd);
    74         if(ans < 0) puts("-1");
    75         else printf("%.9f
    ", ans);
    76     }
    77 
    78     return 0;
    79 }
    代码君
  • 相关阅读:
    Codeforces 611C. New Year and Domino 动态规划
    POJ2585 Window Pains 拓扑排序
    HDOJ1242 Rescue(营救) 搜索
    codeforces 数字区分 搜索
    ZOJ2412 Farm Irrigation(农田灌溉) 搜索
    hdu 4389 X mod f(x) 数位dp
    hdu 4734 F(x) 数位dp
    Codeforces Beta Round #51 D. Beautiful numbers 数位dp
    hdu 3652 B-number 数位dp
    bzoj 1026: [SCOI2009]windy数 数位dp
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4703923.html
Copyright © 2020-2023  润新知