zoukankan      html  css  js  c++  java
  • 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 ;
    }
  • 相关阅读:
    POJ 3041 Asteroids 最小点覆盖 == 二分图的最大匹配
    POJ 3083 Children of the Candy Corn bfs和dfs
    POJ 2049 Finding Nemo bfs 建图很难。。
    POJ 2513 Colored Sticks 字典树、并查集、欧拉通路
    POJ 1013 Counterfeit Dollar 集合上的位运算
    POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
    无聊拿socket写的100以内的加法考试。。。
    POJ 1753 Flip Game
    初学socket,c语言写的简单局域网聊天
    汇编语言 复习 第十一章 标志寄存器
  • 原文地址:https://www.cnblogs.com/misty1/p/2633774.html
Copyright © 2011-2022 走看看