B2241 打地鼠 暴力模拟

大水题!!!30分钟AC(算上思考时间),直接模拟就行,加一个判断约数的剪枝,再多加几个剪枝就可以过(数据巨水)

我也就会做暴力的题了。

题干:

Description

打地鼠是这样的一个游戏:地面上有一些地鼠洞,地鼠们会不时从洞里探出头来很短时间后又缩回洞中。玩家的目标是在地鼠伸出头时,用锤子砸其头部,砸到的地鼠越多分数也就越高。

游戏中的锤子每次只能打一只地鼠,如果多只地鼠同时探出头,玩家只能通过多次挥舞锤子的方式打掉所有的地鼠。你认为这锤子太没用了,所以你改装了锤子,增加了锤子与地面的接触面积,使其每次可以击打一片区域。如果我们把地面看做M*N的方阵,其每个元素都代表一个地鼠洞,那么锤子可以覆盖R*C区域内的所有地鼠洞。但是改装后的锤子有一个缺点:每次挥舞锤子时,对于这R*C的区域中的所有地洞,锤子会打掉恰好一只地鼠。也就是说锤子覆盖的区域中,每个地洞必须至少有1只地鼠,且如果某个地洞中地鼠的个数大于1,那么这个地洞只会有1只地鼠被打掉,因此每次挥舞锤子时,恰好有R*C只地鼠被打掉。由于锤子的内部结构过于精密,因此在游戏过程中你不能旋转锤子(即不能互换R和C)。

你可以任意更改锤子的规格(即你可以任意规定R和C的大小),但是改装锤子的工作只能在打地鼠前进行(即你不可以打掉一部分地鼠后,再改变锤子的规格)。你的任务是求出要想打掉所有的地鼠,至少需要挥舞锤子的次数。

Hint:由于你可以把锤子的大小设置为1*1,因此本题总是有解的。

Input

 第一行包含两个正整数M和N;

下面M行每行N个正整数描述地图,每个数字表示相应位置的地洞中地鼠的数量。

Output

输出一个整数,表示最少的挥舞次数。

Sample Input
3 3
1 2 1
2 4 2
1 2 1

Sample Output

4


【样例说明】

使用2*2的锤子,分别在左上、左下、右上、右下挥舞一次。


【数据规模和约定】

对于100%的数据,1<=M,N<=100,其他数据不小于0,不大于10^5

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
int n,m,tot = 0,s = 0;
int mp[105][105],k[105][105];
bool judge(int l,int r)
{
    duke(i,1,n)
    {
        duke(j,1,m)
        k[i][j] = mp[i][j];
    }
    duke(i,1,n - l + 1)
    {
        duke(j,1,m - r + 1)
        {
            if(k[i][j] != 0)
            {
                int w = k[i][j];
                duke(x,i,i + l - 1)
                {
                    duke(y,j,j + r - 1)
                    {
                        k[x][y] -= w;
                        if(k[x][y] < 0)
                        {
                            return false;
                        }
                    }
                }
            }
        }
    }
    duke(i,1,n)
    {
        duke(j,1,m)
        {
            if(k[i][j] != 0)
            return false;
        }
    }
    return true;
}
int main()
{
    read(n);read(m);
    tot = n * m;
    duke(i,1,n)
    {
        duke(j,1,m)
        {
            read(mp[i][j]);
            s += mp[i][j];
        }
    }
    lv(i,tot,1)
    {
        if(s % i == 0)
        {
            duke(j,1,n)
            {
                if(i % j == 0 && (i / j) <= m)
                {
                    if(judge(j,i / j) == true)
                    {
                        printf("%d
",s / i);
                        return 0;
                    }
                }
            }
        }
    }
    return 0;
}
/*
3 3
1 2 1
2 4 2
1 2 1
*/
原文地址:https://www.cnblogs.com/DukeLv/p/9519997.html