码迷,mamicode.com
首页 > 其他好文 > 详细

[POI2006]ORK-Ploughing

时间:2018-02-25 13:18:36      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:需要   down   tchar   read   blog   矩形   name   reg   std   

[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\n",Ans);
    return 0;
}

[POI2006]ORK-Ploughing

标签:需要   down   tchar   read   blog   矩形   name   reg   std   

原文地址:https://www.cnblogs.com/sdzwyq/p/8468895.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!