• USACO 4.3.1 Buy Low, Buy Lower


    线性DP, 笨得WA了10次才AC,而且高精度加法还是借用的别人的,自己的压位高精度大数算的好奇怪。。。
    本题的重点在于第二问的判重。可以证明,对于相同price的i, j(i<j),应该选择j,因为j包含i的所有情况。
    那么怎么判断某个price是待计算的i前面的最后一个那个j呢,这里我实在太挫没有思路。
    后来参考了别人的做法,我们可以给每一个j构造一个next指针指向下一个相同数字的下标,如果这个下标>i那么就表明j是最后一个。
    然后就很简单了,把所有的最后一个加起来就行了。不过本题要使用高精度算法,总时间复杂度为O(N2)。
    Compile: OK
    
    Executing...
       Test 1: TEST OK [0.011 secs, 5896 KB]
       Test 2: TEST OK [0.011 secs, 5896 KB]
       Test 3: TEST OK [0.011 secs, 5896 KB]
       Test 4: TEST OK [0.011 secs, 5896 KB]
       Test 5: TEST OK [0.011 secs, 5896 KB]
       Test 6: TEST OK [0.022 secs, 5896 KB]
       Test 7: TEST OK [0.032 secs, 5896 KB]
       Test 8: TEST OK [0.011 secs, 5896 KB]
       Test 9: TEST OK [0.065 secs, 5896 KB]
       Test 10: TEST OK [0.248 secs, 5896 KB]
    
    All tests OK.

    Your program ('buylow') produced all correct answers! This is your submission #11 for this problem. Congratulations!

     1 #include <iostream>
     2 #include <iomanip>
     3 #include <cstring>
     4 #include <cstdio>
     5 using namespace std;
     6 
     7 int N, price[5001];
     8 int eqn[5001];
     9 
    10 int dp[5001];
    11 
    12 struct bign
    13 {
    14     char n[500];
    15     int len;
    16     bign():len(1)
    17     {
    18         memset(n,0,sizeof(n));
    19     }
    20     void operator = (const int v)
    21     {
    22         len = 1;
    23         n[0] = v;
    24     }
    25 
    26     void operator += (const bign &rhs)
    27     {
    28         if(rhs.len>len)
    29             len=rhs.len;
    30         for(int i=0;i<len;++i)
    31         {
    32             n[i]+=rhs.n[i];
    33             if(n[i]>9)
    34             {
    35                 ++n[i+1];
    36                 n[i]-=10;
    37             }
    38         }
    39         if(n[len])
    40             ++len;
    41     }
    42     void print()
    43     {
    44         for(int i=len-1;i>=0;--i)
    45             cout << (int)n[i];
    46     }
    47 }dp2[5001];
    48 
    49 int main(void)
    50 {
    51     freopen("buylow.in", "r", stdin);
    52     freopen("buylow.out", "w", stdout);
    53     int i, m;
    54 
    55     cin >> N;
    56     for(i=0; i<N; ++i) cin >> price[i];
    57     N++;    // 增加一个超级节点, price[supernode] = 0;
    58 
    59     for(i=0; i<N-1; ++i) {
    60         int j;
    61         for(j=i+1; j<N; ++j)
    62             if (price[j] == price[i]) {
    63                 eqn[i] = j;
    64                 break;
    65             }
    66         if (j >= N) eqn[i] = N;
    67     }
    68     eqn[N-1] = N;
    69 
    70     for(i=0; i<N; ++i) {
    71         dp[i] = 1;
    72         dp2[i] = 1;
    73         int j;
    74         for(j=0; j<i; ++j) {
    75             if (price[i] < price[j]) {
    76                 if (eqn[j] > i) {
    77                     const int k = dp[j] + 1;
    78                     if (k > dp[i]) {
    79                         dp[i] = k;
    80                         dp2[i] = dp2[j];
    81                     } else if (k == dp[i])
    82                         dp2[i] += dp2[j];
    83                 }
    84             }
    85         }
    86     }
    87     cout << dp[N-1] - 1 << ' ';
    88     dp2[N-1].print();
    89     cout << endl;
    90 
    91     return 0;
    92 }

    2014/5/20更新:

    终于用上自己的高精度了,效率貌似还可以。

    Compiling...
    Compile: OK

    Executing...
       Test 1: TEST OK [0.008 secs, 5400 KB]
       Test 2: TEST OK [0.011 secs, 5400 KB]
       Test 3: TEST OK [0.008 secs, 5400 KB]
       Test 4: TEST OK [0.008 secs, 5400 KB]
       Test 5: TEST OK [0.014 secs, 5400 KB]
       Test 6: TEST OK [0.024 secs, 5400 KB]
       Test 7: TEST OK [0.022 secs, 5400 KB]
       Test 8: TEST OK [0.024 secs, 5400 KB]
       Test 9: TEST OK [0.054 secs, 5400 KB]
       Test 10: TEST OK [0.270 secs, 5400 KB]

    All tests OK.
    #include <iostream>
    #include <iomanip>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    int N, price[5001];
    int eqn[5001];
    
    int dp[5001];
    
    #define min(a,b)    ((a)>(b)?(b):(a))
    #define max(a,b)    ((a)>(b)?(a):(b))
    
    #define BIGNUM_LL            100
    #define BIGNUM_BL            "4"
    #define BIGNUM_MOD            10000UL
    typedef typeof(BIGNUM_MOD) bignum_block;
    
    struct bignum {
        unsigned len;
        bignum_block blks[BIGNUM_LL];
    
        bignum() {blks[0]=0, len=1;}
    
        bignum(unsigned num) {
            len = 0;
            while(num) {
                blks[len++] = num % BIGNUM_MOD;
                num /= BIGNUM_MOD;
            }
        }
    
        void operator += (bignum &b) {
            int i;
            bignum_block carry;
    
            i = len; do blks[i++] = 0; while(i<=b.len);
    
            carry = i = 0;
            for(; i<b.len; ++i) {
                blks[i] += b.blks[i];
                blks[i+1] += blks[i] / BIGNUM_MOD;
                blks[i] %= BIGNUM_MOD;
            }
            for(; i<len; ++i) {
                blks[i+1] +=  blks[i] / BIGNUM_MOD;
                blks[i] %= BIGNUM_MOD;
            }
            len = i + (blks[i] > 0);
        }
    
        void print() {
            printf("%d", blks[len-1]);
            for(int i=len-1; i--; )
                printf("%0" BIGNUM_BL "d", blks[i]);
        }
    }dp2[5001];
    
    int main(void)
    {
        freopen("buylow.in", "r", stdin);
        freopen("buylow.out", "w", stdout);
        int i, m;
    
        cin >> N;
        for(i=0; i<N; ++i) cin >> price[i];
        N++;    // 增加一个超级节点, price[supernode] = 0;
    
        for(i=0; i<N-1; ++i) {
            int j;
            for(j=i+1; j<N; ++j)
                if (price[j] == price[i]) {
                    eqn[i] = j;
                    break;
                }
            if (j >= N) eqn[i] = N;
        }
        eqn[N-1] = N;
    
        for(i=0; i<N; ++i) {
            dp[i] = 1;
            dp2[i] = 1;
            int j;
            for(j=0; j<i; ++j) {
                if (price[i] < price[j]) {
                    if (eqn[j] > i) {
                        const int k = dp[j] + 1;
                        if (k > dp[i]) {
                            dp[i] = k;
                            dp2[i] = dp2[j];
                        } else if (k == dp[i])
                            dp2[i] += dp2[j];
                    }
                }
            }
        }
        cout << dp[N-1] - 1 << ' ';
        dp2[N-1].print();
        cout << endl;
    
        return 0;
    }
  • 相关阅读:
    css text-transform 属性
    CSS3 @media编写响应式页面
    css :first child与:first-of-type的区别
    前端外语网站合集
    webpack配置自动添加CSS3前缀
    vue中extend/component/mixins/extends的区别
    js缓动函数
    [LeetCode] 78. 子集
    [LeetCode] 76. 最小覆盖子串
    [LeetCode] 75. 颜色分类
  • 原文地址:https://www.cnblogs.com/e0e1e/p/usaco_buylow.html
Copyright © 2020-2023  润新知