zoukankan      html  css  js  c++  java
  • 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
    */
  • 相关阅读:
    hdu 4002 Find the maximum
    hdu 2837 坑题。
    hdu 3123
    zoj Treasure Hunt IV
    hdu 2053 Switch Game 水题一枚,鉴定完毕
    poj 1430 Binary Stirling Numbers
    hdu 3037 Saving Beans
    hdu 3944 dp?
    南阳oj 求N!的二进制表示最低位的1的位置(从右向左数)。
    fzu 2171 防守阵地 II
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9519997.html
Copyright © 2011-2022 走看看