zoukankan      html  css  js  c++  java
  • poj 3605 Sheryl's Circuit I 代码

    http://poj.org/problem?id=3605

       

      这个暑假的个人赛打的一塌糊涂...成绩有多难看还真不想说...

      这么多场个人赛,暴露出我的知识面是多么狭窄..可能也是跟我考试前荒废了那么一段时间是有关的..

      

      记录比赛中一道无聊的,超简单的,可是我那时做不出的一道树dp中最水的题。题意很简单的,不解释太多,就简单说一下我的做法。一棵与或表达式树,操作符都已经排好序了,于是我从最底层开始,逐层往上dp。dp数组是储存该节点从0变成1最少要改变多少个控制信号,

      在每一层里,如果是与:dp[i] = dp[i << 1] + dp[i << 1 | 1];

    如果是或:dp[i] = min2(dp[i << 1] + dp[i << 1 | 1], min2(dp[i << 1 | 1], dp[i << 1]));

      有一个很关键的地方是,除了第一次从0变1要改变dp[0]次,其他任何一次无论是从0变成1还是从1变成0,都只需改变一个控制信号。其实原因很简单,既然能找到一个从初始状态(全部是0)改变dp[0]次就可以把输出信号变成1的方法,那么如果只改变dp[0]-1次,这时的输出必然是0。也就是说,除了第一次从0变成1是要找最小操作,其余都只需1步的操作就可以完成了。

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 
     5 #define debug 0
     6 
     7 int min2(int _a, int _b){return _a < _b ? _a : _b;}
     8 int max2(int _a, int _b){return _a > _b ? _a : _b;}
     9 
    10 int dp[8200];
    11 int op[8200];
    12 char s[10005];
    13 
    14 void init(int k){
    15     int end = 1 << k;
    16 
    17     for (int i = 0; i < end; i++){
    18         dp[i] = 1;
    19     }
    20 }
    21 
    22 int deal(int k){
    23     if (!k) return dp[0];
    24     int len = 1 << (k - 1);
    25 
    26     for (int i = 0; i < len; i++){
    27         int p = i + len;
    28 
    29         if (op[p]){
    30             dp[i] = dp[i << 1] + dp[i << 1 | 1];
    31         }
    32         else{
    33             dp[i] = min2(dp[i << 1] + dp[i << 1 | 1], min2(dp[i << 1 | 1], dp[i << 1]));
    34         }
    35     }
    36     #if debug
    37     for (int i = 0; i < len << 1; i++){
    38         printf("%d\n", dp[i]);
    39     }
    40     puts("");
    41     #endif
    42 
    43     return deal(k - 1);
    44 }
    45 
    46 int cnt(int n){
    47     int k = -1;
    48 
    49     while (n){
    50         k++;
    51         n /= 2;
    52     }
    53 
    54     return k;
    55 }
    56 
    57 int main(){
    58     int c;
    59 
    60     scanf("%d", &c);
    61 
    62     while (c--){
    63         int n;
    64 
    65         scanf("%d", &n);
    66         scanf("%s", s);
    67         for (int i = 1; i < n; i++){
    68             scanf("%d", &op[i]);
    69         }
    70 
    71         init(cnt(n));
    72         int tmp = deal(cnt(n));
    73         #if debug
    74         printf("cnt %d  tmp %d\n", cnt(n), tmp);
    75         #endif
    76 
    77         int len = strlen(s);
    78         int p = 0, cnt = 0;
    79 
    80         while (p < len && s[p] == '0') p++;
    81         if (p != len){
    82             cnt += tmp;
    83         }
    84         for (int i = p + 1; i < len; i++){
    85             if (s[i] != s[i - 1]) cnt++;
    86         }
    87         printf("%d\n", cnt);
    88     }
    89 
    90     return 0;
    91 }
  • 相关阅读:
    UVA 254 Towers of Hanoi
    UVA 701 The Archeologists' Dilemma
    UVA 185 Roman Numerals
    UVA 10994 Simple Addition
    UVA 10570 Meeting with Aliens
    UVA 306 Cipher
    UVA 10160 Servicing Stations
    UVA 317 Hexagon
    UVA 10123 No Tipping
    UVA 696 How Many Knights
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_3605_Lyon.html
Copyright © 2011-2022 走看看