zoukankan      html  css  js  c++  java
  • [POI2006]ORK-Ploughing

    [POI2006]ORK-Ploughinghttps://www.luogu.org/problemnew/show/P3444

    题目描述

    (Byteasar) 想耕种他那块矩形的田,他每次能耕种矩形的一边(上下左右都行), 在他每次耕完后,剩下的田也一定是矩形,每块小区域边长为 (1),耕地的长宽分 别为 (m)(n),不幸的是 (Byteasar) 只有一匹老弱的马,从马开始耕地开始,只有当 它耕完了一边才会停下休息。但有些地会非常难耕以至于马会非常的累,因此 (Byteasar) 需要特别小心。当耕完了一边之后,马可以停下来休息恢复体力。每块 地耕种的难度不一,但是 (Byteasar) 都非常清楚。我们将地分成 (m*n) 块单位矩形 ——我们用坐标((I,j))来定义它们。每块地都有一个整数 (T[I,J]),来定义((I,j))的耕 种难度。所以每次马耕一边地时的难度就是所有它耕种的地的难度总和,对于这 匹虚弱的马而言,这个值不能超过他的体力值。(Byteasar) 想知道在马不死掉的情 况下最少需要耕多少次才能把地耕完。

    输入格式:

    第一行三个整数, (K,M,N)(1<=k<=200 000 000),(1<=m,n<=2000).其中 (K) 表示马的体力 值。 接下来 (N) 行每行 (M) 个整数表示难度值。((0<=)难度值(<=10 000))

    输出格式:

    一个整数表示最少的耕种次数(保证马能耕完)。

    输入样例:

    12 6 4
    6 0 4 8 0 5
    0 4 5 4 6 0
    0 5 6 5 6 0
    5 4 0 0 5 4

    输出样例:

    8


    贪心:
    最少次数:(min(n,m)):直接只横切或只纵切切完
    最多次数:(n+m):既横切又纵切
    贪心策略:先优先横切,枚举切左边的次数([1,m]),尽可能少切右边
    再优先纵切,枚举切上面的次数([1,n]),尽可能少切下边
    所有次数取(min)即可

    前缀和优化查询O(1)
    存在无解的情况返回inf
    
    #define RG register
    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=2005;
    inline int read()
    {
        RG int x=0,w=1;RG char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    int k,m,n,Ans=1e9;
    int a[N][N],r[N][N],l[N][N];
    inline int del1(int lim,int L,int R,int U,int D)
    {
        int Sum=0;
        while(L<=R&&U<=D)
        {
            Sum++;
            if(l[D][L]-l[U-1][L]<=k){L++;continue;}
            if(l[D][R]-l[U-1][R]<=k){R--;continue;}
            if((r[U][R]-r[U][L-1]<=k)&&(U<=lim)){U++;continue;}
            if(r[D][R]-r[D][L-1]<=k)D--;
            else return 1e9;
        }
        return Sum;
    }
    inline int del2(int lim,int L,int R,int U,int D)
    {
        int Sum=0;
        while(L<=R&&U<=D)
        {
            Sum++;
            if(r[U][R]-r[U][L-1]<=k){U++;continue;}
            if(r[D][R]-r[D][L-1]<=k){D--;continue;}
            if((l[D][L]-l[U-1][L]<=k)&&(L<=lim)){L++;continue;}
            if(l[D][R]-l[U-1][R]<=k)R--;
            else return 1e9;
        }
        return Sum;
    }
    int main()
    {
        k=read();
        m=read();
        n=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                a[i][j]=read();
                r[i][j]=r[i][j-1]+a[i][j];
                l[i][j]=l[i-1][j]+a[i][j];
            }
        for(int i=0;i<n;i++)Ans=min(Ans,del1(i,1,m,1,n));
        for(int i=0;i<m;i++)Ans=min(Ans,del2(i,1,m,1,n));
        printf("%d
    ",Ans);
        return 0;
    }
    
  • 相关阅读:
    net.sf.json Maven依赖配置
    springboot 测试 出错
    PowerDesigner 中SQL文件、数据库表反向生成PDM
    魔板问题(搜索)
    九宫重排(搜索)
    选点(树的遍历)
    【搜索】桐桐的运输方案
    细胞(搜索)
    传球游戏(dp)
    脚本_检测mysql存活状态
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/8468895.html
Copyright © 2011-2022 走看看