poj 2029 Get Many Persimmon Trees
呃, 水题一枚,暴力就可以轻松过,但是还是想通过这种水题来让自己熟悉一下学过的算法,于是用了几种方法完成,呵呵,收获还是很多的~
1、暴力过了一下,1A,呃,这个代码就不贴了,自认为代码写的还是很烂的,跑了16ms。
2、二维树状数组。通过它终于弄明白二维树状数组是怎样求区间和的了。s[i][j] 表示从( 1 , 1 )->( i , j )的和,则要求( xi , yi )->( xj , yj )矩形的和话,则要表示为
s[xj][yj] + s[xi-1][yi-1] - s[xi-1][yj] - s[xj][yi-1] ,其实一画图就能明白的,
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <queue> #include <math.h> #define N 102 using namespace std; int ss[N][N] , w , h ; int lowbit( int x ) { return x & ( -x ); } void add ( int x , int y , int c ) { int i , j ; for ( i = x ; i <= w ; i+= lowbit( i )) for ( j = y ; j <= h ; j+= lowbit( j )) ss[i][j] += c ; } int sum ( int x , int y ) { int sx = 0 ; for ( int i = x ; i > 0 ; i -= lowbit( i )) for ( int j = y ; j > 0 ; j -= lowbit( j )) sx += ss[i][j] ; return sx ; } int main() { int n , x , y , i , j ; while ( scanf( "%d" , &n ) , n ) { scanf( "%d%d" , &w , &h ); memset( ss , 0 , sizeof( ss )); for ( i = 0 ; i < n ; i++ ) { scanf( "%d%d" , &x , &y ); add( x , y , 1 ); } scanf( "%d%d" , &x , &y ); int maxx = -1 ; for ( i = x ; i <= w ; i++ ) { for ( j = y ; j <= h ; j++ ) { int sx = sum ( i , j ) + sum ( i - x , j - y ) - sum ( i - x , j ) - sum( i , j - y ); if ( sx > maxx ) maxx = sx ; } } cout<<maxx<<endl; } return 0 ; }
3、动态规划,其实这题在训练计划上是属于较复杂的dp,但是我实在没想出来用dp怎么做,曾想过,要不把每个矩形的和存起来在用dp求最大值,但是一想,这样还不如直接暴力呢,然后上网上搜搜大牛们都是怎么用的dp,结果傻眼了,原来是用dp求各个矩形的和,然后在枚举求出最大值,好吧,这样做和上面用二维树状数组其实是一样的。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #define N 102 using namespace std ; int dp[N][N] , w , h ; int max ( int x , int y ) { return x > y ? x : y ; } int main() { int n , i , j , x , y ; while ( scanf( "%d" , &n ) , n ) { scanf( "%d%d" , &w , &h ); memset( dp , 0 , sizeof( dp )); for ( i = 0 ; i < n ; i++ ) { scanf( "%d%d" , &x , &y ); dp[x][y] = 1 ; } /*for ( i = 1 ; i <= w ; i++ ) { for ( j = 1 ; j <= h ; j++ ) cout<<dp[i][j]<<" "; cout<<endl; } cout<<endl;*/ for ( i = 1 ; i <= w ; i++ ) for ( j = 1 ; j <= h ; j++ ) dp[i][j] += dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] ; /*for ( i = 1 ; i <= w ; i++ ) { for ( j = 1 ; j <= h ; j++ ) cout<<dp[i][j]<<" "; cout<<endl; }*/ scanf( "%d%d" , &x , &y ); int maxx = -1 ; for ( i = x ; i <= w ; i++ ) for ( j = y ; j <= h ; j++ ) maxx = max ( maxx , dp[i][j] + dp[i-x][j-y] - dp[i-x][j] - dp[i][j-y] ); cout<<maxx<<endl; } return 0 ; }