zoj 2900 DP(线段树优化)
2014-04-12 10:52
381 查看
同样是暴力,别人能过,我不能过,生活有的时候就是这么无奈。
dp【i】【j】【k】表示前i个数取j个,最后一和是k的个数
然后改变dp顺序可以将三维变为2维
注意下一下细节的地方。。。。不然这样暴力DP会超时
还有一种就是用线段树来优化。。。。。优化到3770ms。。。。。
不优化是6000+ms。。。。
有一点要注意的就是不能一个都没有。。。
AC代码如下:
线段树优化:
没用线段树优化的话要注意一些细节。。。。
dp【i】【j】【k】表示前i个数取j个,最后一和是k的个数
然后改变dp顺序可以将三维变为2维
注意下一下细节的地方。。。。不然这样暴力DP会超时
还有一种就是用线段树来优化。。。。。优化到3770ms。。。。。
不优化是6000+ms。。。。
有一点要注意的就是不能一个都没有。。。
AC代码如下:
线段树优化:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; int dp[2200][110]; int N, K, P, M; int num[2200]; int now; int sum[2200][1000]; int lc( int root ){ return 2 * root; } int rc( int root ){ return 2 * root + 1; } void Up( int pos, int root ){ sum[pos][root] = ( sum[pos][lc(root)] + sum[pos][rc(root)] ) % M; } void Updata( int pos, int k, int number, int l, int r, int root ){ if( l == k && r == k ){ sum[pos][root] = number % M; return; } int mid = ( l + r ) / 2; if( k <= mid ) Updata( pos, k, number, l, mid, lc( root ) ); else Updata( pos, k, number, mid + 1, r, rc( root ) ); Up( pos, root ); } int query( int pos, int L, int R, int l, int r, int root ){ if( L <= l && R >= r ){ return sum[pos][root]; } int ans = 0; int mid = ( l + r ) / 2; if( L <= mid ) ans = ( ans + query( pos, L, R, l, mid, lc( root ) ) ) % M; if( R >= mid + 1 ) ans = ( ans + query( pos, L, R, mid + 1, r, rc( root ) ) ) % M; return ans % M; } int main(){ while( scanf( "%d%d%d%d", &N, &K, &P, &M ) != EOF ){ int ttmax = 0; int ttmin = 100; for( int i = 1; i <= N; i++ ){ scanf( "%d", &num[i] ); ttmax = max( ttmax, num[i] ); ttmin = min( ttmin, num[i] ); } memset( dp, 0, sizeof( dp ) ); memset( sum, 0, sizeof( sum ) ); for( int i = 1; i <= N; i++ ){ for( int j = i; j >= 1; j-- ){ if( j == 1 ){ dp[j][num[i]] = ( dp[j][num[i]] + 1 ) % M; Updata( j, num[i], dp[j][num[i]], 0, 100, 1 ); } int temp = 0, a, b; a = num[i] - P; if( a < ttmin ) a = ttmin; b = num[i] + P; if( b > ttmax ) b = ttmax; temp = query( j - 1, a, b, 0, 100, 1 ); dp[j][num[i]] = ( dp[j][num[i]] + temp ) % M; Updata( j, num[i], dp[j][num[i]], 0, 100, 1 ); } } int ans = 0; for( int i = K == 0 ? 1 : K; i <= N; i++ ){ ans = ( ans + query( i, 0, 100, 0, 100, 1 ) ) % M; } // if( K == 0 ) ans = ( ans + 1 ) % M; cout << ans << endl; } return 0; }
没用线段树优化的话要注意一些细节。。。。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; int dp[2200][110]; int N, K, P, M; int num[2200]; int now; int main(){ while( scanf( "%d%d%d%d", &N, &K, &P, &M ) != EOF ){ int ttmax = 0; for( int i = 1; i <= N; i++ ){ scanf( "%d", &num[i] ); ttmax = max( ttmax, num[i] ); } memset( dp, 0, sizeof( dp ) ); for( int i = 1; i <= N; i++ ){ for( int j = i; j > 1; j-- ){ int temp = 0; for( int k = num[i] - P; k <= num[i] + P && k <= ttmax; k++ ){ if( k < 1 ) continue; temp = ( temp + dp[j-1][k] ) % M; } dp[j][num[i]] = ( dp[j][num[i]] + temp ) % M; } dp[1][num[i]]++; } int ans = 0; for( int i = K == 0 ? 1 : K; i <= N; i++ ){ for( int j = 0; j <= ttmax; j++ ){ ans = ( ans + dp[i][j] ) % M; } } // if( K == 0 ) ans++; cout << ans << endl; } return 0; }
相关文章推荐
- TOJ 4369 ZOJ 3632 Watermelon Full of Water / 线段树优化DP
- ZOJ-3349 Special Subsequence 线段树优化DP
- ZOJ 3349 Special Subsequence(线段树优化DP)
- zoj 3349 Special Subsequence 【离散化二分 + 线段树优化dp】
- zoj 3349 简单DP 线段树或树状数组优化
- bzoj 4712: 洪水 树链剖分+线段树优化dp
- hdu45221——小明系列问题——小明序列 线段树优化dp
- 奶牛抗议——DP之线段树优化
- Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake(线段树+离散化优化DP)
- 线段树和单调队列优化DP
- Codeforces 629D Babaei and Birthday Cake 【线段树优化dp】
- hdu 4521(线段树优化dp)
- ZOJ 3690 Choosing number(dp矩阵优化)
- ZOJ 3632 Watermelon Full of Water (线段树 区间更新 + dp)
- cf474e Pillars(线段树优化dp)
- ZOJ 2561 Order-Preserving Codes(四边形优化DP)
- zoj3632 Watermelon Full of Water 线段树,dp
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
- HDOJ 3415 Max Sum of Max-K-sub-sequence(线段树优化DP)
- Codeforces Round #271 (Div. 2) E. Pillars 线段树优化dp