【bzoj2241】[SDOI2011]打地鼠  暴力+乱搞

2241: [SDOI2011]打地鼠

Time Limit: 10 Sec Memory Limit: 512 MB

Submit: 1069 Solved: 679

[Submit][Status][Discuss]

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

HINT

Source

第一轮Day1

题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=2241

题意: 中文题。。

思路

枚举i*j是(n^6),加上各种优化及乱搞即可;

1.首先锤子的大小先横行(列)枚举,筛法原理剪支;

        if(sum%i!=0||!can(i,1))
        {
            for(int j=i;j<=n;j+=i)
            lin[j]=-1;
        }

2.搜的判断条件:

if(sum/(i*j)>ans) continue;

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int ma[101][101];
int tmp[101][101];
int n,m;
int t[101];
int lin[101];
int row[101];
int sum;
int ans;
bool can(int x,int y)
{
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    tmp[i][j]=ma[i][j];

    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    if(tmp[i][j])
    {
        if(i+x>n+1||j+y>m+1) return 0;
        int tt=tmp[i][j];
        for(int ii=i;ii<i+x;ii++)
        {
            for(int jj=j;jj<j+y;jj++)
            {
                tmp[ii][jj]-=tt;
                if(tmp[ii][jj]<0) return 0;
            }

        }
    }
    ans=sum/(x*y);
    return 1;

}
int main()
{
    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        scanf("%d",&ma[i][j]);
        sum+=ma[i][j];
    }
    can(1,1);
    for(int i=2;i<=n;i++)
    if(!lin[i])
    {
        if(sum%i!=0||!can(i,1))
        {
            for(int j=i;j<=n;j+=i)
            lin[j]=-1;
        }
    }
    for(int i=2;i<=m;i++)
    if(!row[i])
    {
        if(sum%i!=0||!can(1,i))
        {
            for(int j=i;j<=m;j+=i)
            row[j]=-1;
        }
    }
    for(int i=2;i<=n;i++)
    if(!lin[i])
    {
        for(int ii=2;ii<=m;ii++)
            t[ii]=row[ii];
        for(int j=2;j<=m;j++)
        if(!t[j])
        {
            if(sum/(i*j)>ans) continue;
            if(sum%(i*j)!=0||!can(i,j))
            for(int k=j;k<=m;k+=j)
            t[k]=-1;
        }
    }
    printf("%d\n",ans);
}
时间: 2024-10-05 13:28:11

【bzoj2241】[SDOI2011]打地鼠  暴力+乱搞的相关文章

bzoj 2241: [SDOI2011]打地鼠 暴力

2241: [SDOI2011]打地鼠 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 749  Solved: 488[Submit][Status][Discuss] Description 打地鼠是这样的一个游戏:地面上有一些地鼠洞,地鼠们会不时从洞里探出头来很短时间后又缩回洞中.玩家的目标是在地鼠伸出头时,用锤子砸其头部,砸到的地鼠越多分数也就越高. 游戏中的锤子每次只能打一只地鼠,如果多只地鼠同时探出头,玩家只能通过多次挥舞锤子的方式打掉

topcoder-srm610-div2-550(暴力乱搞)

给你一个01矩阵,求其中最大的01交替的矩阵 由于n最大才100,所以直接暴力乱搞 先求出第i行,所有列往上的合法长度,然后枚举以第j列为最左边的列,计算可以得到的最大矩阵 /************************************************************************* > File Name: 2.cpp > Author: ALex > Mail: [email protected] > Created Time: 2015年

BZOJ-2241: [SDOI2011]打地鼠 (模拟+枚举)

2241: [SDOI2011]打地鼠 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1434  Solved: 909[Submit][Status][Discuss] Description 打地鼠是这样的一个游戏:地面上有一些地鼠洞,地鼠们会不时从洞里探出头来很短时间后又缩回洞中.玩家的目标是在地鼠伸出头时,用锤子砸其头部,砸到的地鼠越多分数也就越高. 游戏中的锤子每次只能打一只地鼠,如果多只地鼠同时探出头,玩家只能通过多次挥舞锤子的方式打

Codeforces Gym 100203G Good elements 暴力乱搞

原题链接:http://codeforces.com/gym/100203/attachments/download/1702/statements.pdf 题解 考虑暴力的复杂度是O(n^3),所以我们需要记录所有的ai+aj,如果当前考虑到了ak,那么就去前面寻找ai,使得ak-ai是我们记录过的和.整个算法的复杂度O(n^2). 代码 #include<iostream> #include<cstring> #include<cstdio> #include<

bzoj2241: [SDOI2011]打地鼠

暴力. O(n^6)暴力卡过,72ms. 莫名其妙做这道题时感觉十分烦躁,难受,只能这样了. O(n^4)的方法是这样差分一下.判断的时候tmp=t[i][j],t[i][j]-=tmp,t[i+r][j]+=tmp,t[i][j+c]+=tmp,t[i+r][j+c]-=tmp,同时查看是否合法. 还有一个更优化的是如果r,c不行,r*q和c*q也不行.这个好像就是正解的办法? 为什么上面那俩个那么高的复杂度可以通过我想有这样的原因. 首先必须满足r|m和c|n,这个会去掉大量的判断,其次判断

BNUOJ 39423 暴力乱搞

最有的答案肯定是找到一些点的集合,这些点两两之间是朋友关系. 考虑到n,m比较小,这样的集合最多只有14个点,暴力找点的集合 先找出1 个点的集合,有n个这样的集合 然后找出2个点的集合,找的时候要求编号比之前的大,这样就能保证不重不漏 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cctype> #include<cmath&

codeforces 498D Unbearable Controversy of Being (暴力乱搞)

传送门:点击打开链接 题目大意: 定义下图为"damn rhombus",给定一个有向图,求出有多少个"damn rhombus". 解题思路1: 分析可以得出其实"damn rhombus"的意思就是求a->c通过2个节点中转的个数.也就是说 如果a->c中间中转了x个点,那么对于点对(a,c)来说"damn rhombus"就有C(x,2)个. 那么通过层数为2的bfs就可以得出答案. #include <

POJ 3077-Rounders(水题乱搞)

Rounders Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7697   Accepted: 4984 Description For a given number, if greater than ten, round it to the nearest ten, then (if that result is greater than 100) take the result and round it to th

Ural 1780 Gray Code 乱搞暴力

原题链接:http://acm.timus.ru/problem.aspx?space=1&num=1780 1780. Gray Code Time limit: 0.5 secondMemory limit: 64 MB Denis, Vanya and Fedya gathered at their first team training. Fedya told them that he knew the algorithm for constructing aGray code. Cre