P5917
前言
不用分类讨论。
其实不知道为什么 P1212 和 P5917 两题现有的
但是其实可以不用的,有一种丝毫不用分类讨论而且可以拓展到任意数量矩形的做法。
题意
给定
思路
首先可以先想最优的矩形排列会长成什么样,给一张图:
这个解看起来是最优的。(实际上也是)
那么这个解有什么特点呢?
每个矩形都尽可能地向左下角靠拢。
容易说明,如果一个矩形可以向左下方移动,那这个矩形移动以后这个解不会更劣,如果这个解已经是最优解,那这样做不会影响到这个解的形状,所以只需要统计每个矩形都尽可能地向左下角靠拢的情况就足以求出正确答案。
所以,可以考虑枚举矩形放置的顺序和每个矩形是否旋转
具体地,如果矩形不能向左下方移动,那它的左边界一定紧贴某个矩形的右边界或者紧贴最左边,它的下边界一定紧贴某个矩形的上边界或者紧贴最下边。所以可以考虑枚举一个矩形的左边界在哪里,然后找到最靠下的一个下边界使得这个矩形的放置合法,然后尝试将这个矩形放在这个位置。
注意这样做只保证了矩形不能向下方移动,而没有保证矩形不能向左方移动,但是所有矩形不能向左下方移动的可能性都会被枚举到,所以这样做是可行的。
有一个小优化:第一个放置的矩形一定可以不旋转
然后就做完了,有什么细节问题可以看看代码,时间复杂度是
最后贴上 AC 记录和代码。
#include<cstdio>
#include<cstdlib>
using namespace std;
const int n=4;
int x[10],y[10],i,j,pl[10],bj[10],rev[10],l[10],r[10],d[10],u[10],ans=100000000,wans[1000],tt[1000],top;
int min(int a,int b)
{
if(a<b)
return a;
else
return b;
}
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
void dfs3(int w)
{
int i,j,k,t1=0,t2=0;
if(w>n)
{
for(i=1;i<=n;i++)
if(r[i]>t1)
t1=r[i];
for(i=1;i<=n;i++)
if(u[i]>t2)
t2=u[i];
if(t1>t2)
{
i=t1;
t1=t2;
t2=i;
}
if(t1*t2<ans)
{
ans=t1*t2;
for(i=1;i<=top;i++)
tt[wans[i]]=0;
top=1;
wans[1]=t1;
tt[t1]=1;
}
else if(t1*t2==ans&&tt[t1]==0)
{
tt[t1]=1;
top++;
wans[top]=t1;
}
return;
}
for(i=0;i<w;i++)
{
l[w]=r[i];
if(rev[w]==0)
r[w]=l[w]+x[pl[w]];
else
r[w]=l[w]+y[pl[w]];
t1=1000000;
for(j=0;j<w;j++)
if(u[j]<t1)
{
d[w]=u[j];
if(rev[w]==0)
u[w]=d[w]+y[pl[w]];
else
u[w]=d[w]+x[pl[w]];
for(k=1;k<w;k++)
if(max(d[k],d[w])<min(u[k],u[w])&&max(l[k],l[w])<min(r[k],r[w]))
break;
if(k>=w)
t1=u[j];
}
d[w]=t1;
if(rev[w]==0)
u[w]=d[w]+y[pl[w]];
else
u[w]=d[w]+x[pl[w]];
dfs3(w+1);
}
}
void dfs2(int w)
{
if(w>n)
{
dfs3(1);
return;
}
rev[w]=1;
dfs2(w+1);
rev[w]=0;
dfs2(w+1);
}
void dfs1(int w)
{
int i;
if(w>n)
{
dfs2(2);
return;
}
for(i=1;i<=n;i++)
if(bj[i]==0)
{
bj[i]=1;
pl[w]=i;
dfs1(w+1);
bj[i]=0;
}
}
main()
{
for(i=1;i<=n;i++)
scanf("%d%d",&x[i],&y[i]);
dfs1(1);
top=0;
for(i=1;i<=n*50;i++)
if(tt[i]>0)
{
top++;
wans[top]=i;
}
printf("%d\n",ans);
for(i=1;i<=top;i++)
printf("%d %d\n",wans[i],ans/wans[i]);
}
后记
上面这个做法有拓展性,什么意思呢,就是不一定是 const int n=4; 其中的