【HDU 4925】BUPT 2015 newbie practice #2 div2-C-HDU 4925 Apple Tree

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=102419#problem/C

Description

I’ve bought an orchard and decide to plant some apple trees on it. The orchard seems like an N * M two-dimensional map. In each grid, I can either plant an apple tree to get one apple or fertilize the soil to speed up its neighbors’ production. When a grid is fertilized, the grid itself doesn’t produce apples but the number of apples of its four neighbor trees will double (if it exists). For example, an apple tree locates on (x, y), and (x - 1, y), (x, y - 1) are fertilized while (x + 1, y), (x, y + 1) are not, then I can get four apples from (x, y). Now, I am wondering how many apples I can get at most in the whole orchard? 
 

Input

The input contains multiple test cases. The number of test cases T (T<=100) occurs in the first line of input. 
For each test case, two integers N, M (1<=N, M<=100) are given in a line, which denote the size of the map.
 

Output

For each test case, you should output the maximum number of apples I can obtain.
 

Sample Input

2 2 2 3 3
 

Sample Output

8 32

题意:给你n×m的格子,每个格子你可以选择给1,或者使它上下左右(如果有)的数字乘2,你对每个格子操作的先后顺序是自由的,求所有格子数字总和的最大值。

t组(小于100)数据,n和m(1到100)

题解:要使总和最大,那就每隔一个格子给1,使得每个给1的格子周围都是乘2的格子,这样它就乘了最多次2,比如3行4列

1 0 1 0

0 1 0 1

1 0 1 0

这里0表示使周围的乘2,我们的顺序是先给1,再乘2,于是总和是4+8+16+8+4+8=48

法一。

模拟这些格子,根据n和m,构造出上述的01二维数组,再对每个格子判断周围几个0,然后乘几次2,累加答案

代码:

#include<cstdio>
#include<cstring>

int ma[105][105];
int main()
{
    int n,m,t,k,ans,u,h;
    int ma[105][105];
    scanf("%d",&t);

    while(t--)
    {
        memset(ma,0,sizeof(ma));
        ans=0;
        k=0;
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
        {
            for(int j=0+k; j<m; j+=2)
                ma[i][j]=1;//设置它为1
            k=!k;
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(ma[i][j])
                {
                    h=1;
                    u=0;
                    if(i-1>=0)if(!ma[i-1][j])u++;//如果为0,代表乘2
                    if(i+1<n)if(!ma[i+1][j])u++;
                    if(j-1>=0)if(!ma[i][j-1])u++;
                    if(j+1<m)if(!ma[i][j+1])u++;
                    for(int l=1; l<=u; l++)h*=2;
                    ans+=h;
                }
            }
        }
        printf("%d
",ans);

    }
    return 0;

}

法二。

如果行列数之和为奇数,则给1,并且使它周围为乘2,则这个1就要乘几次2了,根据是否在边缘,判断乘几次2,累加答案

代码:

//code from lyt
#include<cstdio>
using namespace std;
int T;
int n,m;
long long ans=0;
long long now=0;
int main()
{
    scanf("%d",&T);
    while(T)
    {
        scanf("%d%d",&n,&m);
        ans=0;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                if((i+j)&1)
                {
                    now=1;
                    if(i>1)
                        now<<=1;
                    if(j>1)
                        now<<=1;
                    if(i<n)
                        now<<=1;
                    if(j<m)
                        now<<=1;
                    ans+=now;
                }
            }
        }
        printf("%lld
",ans);
        T--;
    }
    return 0;
}

法三。

通过分析推出公式(x表示n,y表示m)

ans=1,当x=1,y=1;

ans=2*(y-1),当x=1,y>1;

ans=(x-1)*2,当x>1,y=1;

ans=(x-1)*8*(y-1),当x>1,y>1;

具体怎么分析推出的,...不详

代码:

//code from zdh
#include<stdio.h>
int T,x,y,s;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&x,&y);
        if(x>1)
        {
            if(y==1)
                s=(x-1)*2;
            else
                s=(x-1)*8*(y-1);
        }
        else
        {
            if(y==1)
                s=1;
            else
                s=2*(y-1);
        }
        printf("%d
",s);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/flipped/p/5103212.html