• P2484 [SDOI2011]打地鼠


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

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

       $n,mle 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;
    }
  • 相关阅读:
    多线程
    IO
    Collections工具类
    File类
    Map
    List与Set接口
    如何把数学作为一种工具
    包装类
    异常
    内部类
  • 原文地址:https://www.cnblogs.com/olinr/p/9580288.html
Copyright © 2020-2023  润新知