USACO 4.3 Buy Low, Buy Lower (DP,高精度,(离散化))
2015-03-26 20:22:33
思路:这道题与POJ1952是一样的... 不过那题数据水,long long可水过。
目前,对于这种求最长下降(/上升)子序列的长度以及种类的问题,我只能想到n^2的方法咯...
考虑到长度最长5000,稍微构造下就能超long long,所以大数模板上好先。
首先,if(v[j] > v[i]) dp[i] = max(dp[i],dp[j + 1]) (j < i) 从朴素的方程出发。
因为要计数,要单独用大数开一个计数cnt数组。
其次,这题求的是种类,要防止重复,所以对于相同的数字,我们计数时只能算位置最靠后的。位置靠后的数字已经包含前面相同数字的种类了。
比如:7 6 5 3 5 4 6 ,当算到4时,往前遍历到两个5,如果都计算的话,会出现两次 7 6 5 这个序列,显然重复。
关于这个问题的解决,用标记数组来标记当前已经出现过的数字。
(1)可以从当前位置往前扫描,把相同的数字标记掉,比较暴力。我poj1952就是这样做的。(2)离散化掉后直接标记数值已经出现。
最后,在统计答案时也要防止重复!同样需要开数组进行标记。
1 /* 2 ID:naturec1 3 PROG: buylow 4 LANG: C++ 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <cstdlib> 9 #include <cmath> 10 #include <vector> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <string> 16 #include <iostream> 17 #include <algorithm> 18 using namespace std; 19 20 #define MEM(a,b) memset(a,b,sizeof(a)) 21 #define REP(i,n) for(int i=1;i<=(n);++i) 22 #define REV(i,n) for(int i=(n);i>=1;--i) 23 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 24 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 25 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 26 #define MP(a,b) make_pair(a,b) 27 28 typedef long long ll; 29 typedef pair<int,int> pii; 30 const int INF = (1 << 30) - 1; 31 const int MAXN = 5010; 32 const int maxn = 100; 33 34 struct bign{ 35 vector<int> s; 36 bign(){ 37 s.clear(); 38 } 39 bign operator = (int val){ 40 s.clear(); 41 while(val){ 42 s.push_back(val % 10); 43 val /= 10; 44 } 45 return *this; 46 } 47 bign operator = (bign B){ 48 s = B.s; 49 return *this; 50 } 51 bign operator + (bign B){ 52 bign res; 53 int c = 0,top = max(s.size(),B.s.size()),v1,v2; 54 for(int i = 0; i < top; ++i){ 55 v1 = i < s.size() ? s[i] : 0; 56 v2 = i < B.s.size() ? B.s[i] : 0; 57 res.s.push_back((v1 + v2 + c) % 10); 58 c = (v1 + v2 + c) / 10; 59 } 60 if(c) res.s.push_back(c); 61 return res; 62 } 63 void print(){ 64 for(int i = s.size() - 1; i >= 0; --i) 65 printf("%d",s[i]); 66 } 67 }; 68 69 int N; 70 int v[MAXN],tv[MAXN]; 71 int dp[MAXN]; 72 int vis[MAXN]; 73 74 bign cnt[MAXN]; 75 76 int main(){ 77 freopen("buylow.in","r",stdin); 78 freopen("buylow.out","w",stdout); 79 scanf("%d",&N); 80 REP(i,N) scanf("%d",v + i),tv[i] = v[i]; 81 sort(tv + 1,tv + N + 1); 82 int sz = unique(tv + 1,tv + N + 1) - tv; 83 REP(i,N) v[i] = lower_bound(tv + 1,tv + sz + 1,v[i]) - tv; 84 int ans = 0; 85 REP(i,N){ 86 MEM(vis,0); 87 dp[i] = 1; 88 cnt[i] = 1; 89 vis[v[i]] = 1; 90 for(int j = i - 1; j >= 1; --j) if(v[j] > v[i]){ 91 if(dp[j] + 1 > dp[i]){ 92 dp[i] = dp[j] + 1; 93 cnt[i] = cnt[j]; 94 } 95 else if(dp[j] + 1 == dp[i]){ 96 if(!vis[v[j]]){ 97 cnt[i] = cnt[i] + cnt[j]; 98 } 99 } 100 vis[v[j]] = 1; 101 } 102 if(dp[i] > ans) ans = dp[i]; 103 } 104 printf("%d ",ans); 105 MEM(vis,0); 106 bign anscnt; 107 anscnt = 0; 108 for(int i = N; i >= 1; --i) if(!vis[v[i]] && dp[i] == ans){ 109 vis[v[i]] = 1; 110 anscnt = anscnt + cnt[i]; 111 } 112 anscnt.print(); 113 puts(""); 114 return 0; 115 }