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)。
本题的重点在于第二问的判重。可以证明,对于相同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; }
This article is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
本文采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。