您的位置:首页 > 其它

bzoj1766: [Ceoi2009]photo

2017-06-08 20:51 405 查看
传送门

跪Claris神犇。

首先得到状态f[i][j][k]表示在i到j的区间内高度大于k的最小矩形数目。

然后就两种转移:分割线或者放尽量大的新矩形。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct P{int x,y;}a[105];
int n,m,A,b[105],c[105],f[105][105][105];
bool cmp(P a,P b){
return a.x==b.x?a.y>b.y:a.x<b.x;
}
int main(){
scanf("%d%d",&n,&A);
for (int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmp);
for (int i=1;i<=n;i++)
if (i==1||a[i].x!=a[i-1].x) a[++m]=a[i];
for (int i=1;i<=m;i++) b[i]=a[i].y;
sort(b+1,b+m+1);
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
if (a[i].y==b[j]){
c[i]=j; break;
}
for (int i=m;i;i--)
for (int j=i;j<=m;j++)
for (int k=m;k;k--){
f[i][j][k]=105;
for (int t=i;t<j;t++)
f[i][j][k]=min(f[i][j][k],f[i][t][k]+f[t+1][j][k]);
int l,r,x,y;
for (l=i;l<=j;l++)
if (c[l]>=k) break;
for (r=j;r>=i;r--)
if (c[r]>=k) break;
if (l>r){
f[i][j][k]=0;
continue;
}
if (l==r){
f[i][j][k]=1;
continue;
}
x=a[r].x-a[l].x; y=A/x;
for (l=i;l<=j;l++)
if (a[l].y>y) break;
for (r=j;r>=i;r--)
if (a[r].y>y) break;
x=105;
for (int t=l;t<=r;t++)
if (a[t].y>y&&c[t]<x) x=c[t];
f[i][j][k]=min(f[i][j][k],f[l][r][x]+1);
}
printf("%d",f[1][m][1]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: