zoukankan      html  css  js  c++  java
  • 《洛谷P2140 小Z的电力管制》

    这题做出来了很有成就感(骄傲.jpg)

    虽然这题没评级,但我感觉应该有紫题难度吧?

    Solution:

    数据很小,然后题目里说了要横纵分解区域。

    所以可以从这里出发,dfs分解区域。

    具体怎么分解:可以发现,如果在这个地方分解开当前区域,那么必须满足两边断电后都能满足。

    如果可以,那么再去看是否能分解到更小的即可。

    做到这里之后,一交,T了。

    显然,过于暴力了。

    考虑记忆化搜素,设dp[x1][y1][x2][y2]表示区域(x1,y1)~(x2,y2)能分解成的最多区域数。

    交了一发又T了,原来一开始我统计区域面积的时候是暴力求的。。显然可以前缀和O(1)求出。

    嗯。AC。

    注意:题目求的是最大的区域最小值。这里一定要判断清楚。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e4+5;
    const int M = 2e4+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    int n,m,u,a[35][35],sum = 0,pre[35][35];
    pii dp[35][35][35][35];
    int cal(int x1,int y1,int x2,int y2)
    {
        return pre[x2][y2]+pre[x1-1][y1-1]-pre[x1-1][y2]-pre[x2][y1-1];
    }
    pii dfs(int x1,int y1,int x2,int y2,int all)
    {
        if(dp[x1][y1][x2][y2].first != 0) return dp[x1][y1][x2][y2];
        if(x1 == x2 && y1 == y2) return pii{1,u-(sum-all)};
        pii tmp;
        tmp.first = 1;
        tmp.second = u-(sum-all);
        for(int i = y1;i < y2;++i)//纵向划分
        {
            int cal1 = cal(x1,y1,x2,i);
            int cal2 = cal(x1,i+1,x2,y2);
            if(sum-cal1 <= u && sum-cal2 <= u)
            {
                pii ma1 = dfs(x1,y1,x2,i,cal1);
                pii ma2 = dfs(x1,i+1,x2,y2,cal2);
                if(ma1.first+ma2.first > tmp.first)
                {
                    tmp.first = ma1.first+ma2.first;
                    tmp.second = min(ma1.second,ma2.second);
                }
                else if(ma1.first+ma2.first == tmp.first) tmp.second = max(tmp.second,min(ma1.second,ma2.second));
            }
        }
        for(int i = x1;i < x2;++i)//横向划分
        {
            int cal1 = cal(x1,y1,i,y2);
            int cal2 = cal(i+1,y1,x2,y2);
            if(sum-cal1 <= u && sum-cal2 <= u)
            {
                pii ma1 = dfs(x1,y1,i,y2,cal1);
                pii ma2 = dfs(i+1,y1,x2,y2,cal2);
                if(ma1.first+ma2.first > tmp.first)
                {
                    tmp.first = ma1.first+ma2.first;
                    tmp.second = min(ma1.second,ma2.second);
                }
                else if(ma1.first+ma2.first == tmp.first) tmp.second = max(tmp.second,min(ma1.second,ma2.second));
            }
        }
        return dp[x1][y1][x2][y2] = tmp;
    }
    int main()
    {
        n = read(),m = read(),u = read();
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= m;++j) a[i][j] = read(),sum += a[i][j];
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= m;++j) pre[i][j] = pre[i][j-1]+pre[i-1][j]-pre[i-1][j-1]+a[i][j];
        pii ans = dfs(1,1,n,m,sum);//左下,右上
        printf("%d %d
    ",ans.first,ans.second);
      //  system("pause");    
    }
    View Code
  • 相关阅读:
    不使用BeanUtils,利用Java反射机制:表单数据自动封装到JavaBean
    VS2010水晶报表的添加与使用
    使用SelectClipRgn注意事项
    使用SelectClipRgn注意事项
    使用事件CreateEvent注意事项
    【转】Delphi内嵌ASM简易教程
    栈顶和栈底示意图
    【转】对ARM堆栈的理解
    UISegmentedControl的基本使用
    C语言小知识总结
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13664728.html
Copyright © 2011-2022 走看看