P2484 [SDOI2011]打地鼠

题意:n*m矩阵,每次操作让p*q大小的子矩阵-1(此子矩阵元素>0)

   让你求得一个p,q使得操作次数最少

   $n,m\le 100$

 

 

首先,枚举p,q肯定是少不了

然后就有了一个剪枝

1、if(step>=ans) return;最优性剪枝

同时,为了使剪枝1更有效,我们要在最快的时间内减小ans

所以

2、p,q倒着枚举!

其次,可以发现,每一次操作会让矩阵减少p*q

因此,如果矩阵元素和不能整除p*q那就不用判断了

3、if(tot%(p*q))continue;可行性剪枝

4、if(tot/(p*q)>ans)continue;可行性剪枝

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
#define int long long
#define olinr return
#define _ 0
#define love_nmr 0
#define DB double
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            f=-f;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
inline void put(int x)
{
    if(x<0)
    {
        x=-x;
        putchar('-');
    }
    if(x>9)
        put(x/10);
    putchar(x%10+'0');
}
int ans;
int n;
int m;
int tot;
int ju[120][120];
int ls[120][120];
inline void dfs(int step,int lst,int x,int y)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            ls[i][j]=ju[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            int xx=i+x-1;
            int yy=j+y-1;
            int minn=0x7fffffff;
            if(xx>n||yy>m) break;
            for(int k=i;k<=xx;k++)
                for(int l=j;l<=yy;l++)
                    if(!ls[k][l])goto girlfriend;
                    else minn=min(minn,ls[k][l]);
            for(int k=i;k<=xx;k++)
                for(int l=j;l<=yy;l++)
                    ls[k][l]-=minn;
            lst-=x*y*minn;
            step+=minn;
            if(step>=ans) return;
            girlfriend:;
        }
    if(!lst)
    {
        ans=min(ans,step);
        return;
    }
}
signed main()
{
    n=read();
    m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            ju[i][j]=read(),ans+=ju[i][j];
    tot=ans;
    for(int i=n;i>=1;i--)
        for(int j=m;j>=1;j--)
        {
            int c=i*j;
            if(tot%c||tot/c>=ans) continue; 
            dfs(0,tot,i,j);
        }
    put(ans);
    olinr ~~(0^_^0)+love_nmr;
}

 

posted @ 2018-09-03 19:00  olinr  阅读(161)  评论(0编辑  收藏  举报