tkj
文章143
标签102
分类0
bzoj 1810: [Ioi2005]gar

bzoj 1810: [Ioi2005]gar

.

题意:一个花园里有n朵花,用两个矩形不相交地框起两部分,使每个矩形内都有k朵花,并最小化周长。
题解:暴力处理出每一行往上和往下最小的周长,每一列往左和往右最小的周长。最后横竖扫一遍就好了。
代码:

#include<bits/stdc++.h>
#define pa pair<int,int>
using namespace std;

int l,w,n,K,sum[300][300],ans=1<<30,s1[300],s2[300],s3[300],s4[300];
pa a[5010];

int get(int x1,int y1,int x2,int y2)
{
    if(x1>x2)
    swap(x1,x2);
    if(y1>y2)
    swap(y1,y2);
    return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
}
int main()
{
    memset(s1,63,sizeof(s1));
    memset(s2,63,sizeof(s2));
    memset(s3,63,sizeof(s3));
    memset(s4,63,sizeof(s4));
    scanf("%d%d%d%d",&l,&w,&n,&K);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&a[i].first,&a[i].second);
        sum[a[i].first][a[i].second]++;
    }/*
    for(int i=1;i<=l;i++)
    {
        for(int j=1;j<=w;j++)
        printf("%d ",sum[i][j]);
        puts("");
    }
    puts("");*/
    for(int i=1;i<=l;i++)
    for(int j=1;j<=w;j++)
    {
        sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    }
    for(int i=1;i<=l;i++)
    for(int j=i;j<=l;j++)
    {
        for(int k=1,l=1;k<=w;k++)
        {
            while(l<k&&get(i,l+1,j,k)>=K)
            l++;
//            printf("%d %d %d %d %d\n",i,l,j,k,get(i,l,j,k));
            if(get(i,l,j,k)==K)
            {
                s1[j]=min(s1[j],(j-i+1+k-l+1)<<1);
                s2[i]=min(s2[i],(j-i+1+k-l+1)<<1);
            }
        }
    }
    for(int i=2;i<=l;i++)
    s1[i]=min(s1[i],s1[i-1]);
    for(int i=l-1;i>0;i--)
    s2[i]=min(s2[i],s2[i+1]);
    for(int i=1;i<=w;i++)
    for(int j=i;j<=w;j++)
    {
        for(int k=1,o=1;k<=l;k++)
        {
            while(o<k&&get(o+1,i,k,j)>=K)
            o++;
            if(get(o,i,k,j)==K)
            {
                s3[j]=min(s3[j],(j-i+1+k-o+1)<<1);
                s4[i]=min(s4[i],(j-i+1+k-o+1)<<1);
            }
        }
    }
    for(int i=2;i<=w;i++)
    s3[i]=min(s3[i],s3[i-1]);
    for(int i=w-1;i>0;i--)
    s4[i]=min(s4[i],s4[i+1]);/*
    for(int i=1;i<=l;i++)
    printf("%d %d\n",s1[i],s2[i]);
    puts("");
    for(int i=1;i<=w;i++)
    printf("%d %d\n",s3[i],s4[i]);*/
    for(int i=1;i<l;i++)
    {
        ans=min(ans,s1[i]+s2[i+1]);
    }
    for(int i=1;i<w;i++)
    {
        ans=min(ans,s3[i]+s4[i+1]);
    }
    if(ans==(1<<30))
    printf("NO");
    else
    printf("%d",ans);
}
本文作者:tkj
本文链接:https://tkj666.github.io/27/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可