下面的代码跑得很快,让我一不小心进入了uva前二十的光荣榜。但是假若我不说我这代码是参考大牛的,我会相当羞愧。大牛
另外,思路是这样的:
先放中间;
再把两侧的分一下类,按力矩大小排序
左边试放一下,右边试放一下。
某种情况下,这个木块一定要现在放。
搜索+剪枝。
剪枝巧妙地令程序跑起来脱离地面。
vis[k]=true;
int &d=P[k].d,&w=P[k].w;
nleft=left+(d+3)*w;nright=right+(3-d)*w;
if(nright>=0) tright=0;
if(nleft>=0 && nright>=0)
{
A[cur]=k;
flag=dfs(nleft,nright,cur+1);
if(flag==2) return 2;
if(flag==-1) break;
}
vis[k]=false;
这段代码尤为关键。
看看vis[k]标记的位置。
超时的做法:
int &d=P[k].d,&w=P[k].w;
nleft=left+(d+3)*w;nright=right+(3-d)*w;
if(nright>=0) tright=0;
if(nleft>=0 && nright>=0)
{
A[cur]=k;
vis[k]=true;
flag=dfs(nleft,nright,cur+1);
vis[k]=false;
if(flag==2) return 2;
if(flag==-1) break;
}
为什么?
因为当flag==-1时,意味着下一层,左边不能放,右边能放。左边不能放,是因为放不下,力矩太打了,因为力矩是经过排序的,下一层的力矩都放不下了,那么这层的这个木块一定要选。反证法证明之。假如不选,那么左边还没有选完,必然要选左边还未放的木块放上去,因为目前这个木块的力矩是最小的,如果这个木块都不选,后面的木块更不用说了,换一个说法就是,not to mention the rest objucts.
巧妙之处:
扩大一倍,将小数变为整数。
排序,为剪枝铺垫。
先放中间的优势策略。
回溯时,将下层的摆放方法传递到这层供剪枝。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int left,right,n,A[25],L[25],R[25],n1,n2;
bool vis[25];
struct Pack
{
int w,d;
} P[25];
int dfs(int left,int right,int cur)
{
if(cur==n) return 2;
int nleft,nright,tleft=1,tright=1,i,flag,k;
for(i=0;i<n1;i++)
{
k=L[i];
if(!vis[k])
{
vis[k]=true;
int &d=P[k].d,&w=P[k].w;
nleft=left+(d+3)*w;nright=right+(3-d)*w;
if(nleft>=0) tleft=0;
if(nleft>=0 && nright>=0)
{
A[cur]=k;
flag=dfs(nleft,nright,cur+1);
if(flag==2) return 2;
if(flag==1) break;
}
vis[k]=false;
}
}
for(i=0;i<n2;i++)
{
k=R[i];
if(!vis[k])
{
vis[k]=true;
int &d=P[k].d,&w=P[k].w;
nleft=left+(d+3)*w;nright=right+(3-d)*w;
if(nright>=0) tright=0;
if(nleft>=0 && nright>=0)
{
A[cur]=k;
flag=dfs(nleft,nright,cur+1);
if(flag==2) return 2;
if(flag==-1) break;
}
vis[k]=false;
}
}
return tleft-tright;
}
int torque(int i)
{
if(P[i].d<0)
return (-3-P[i].d)*P[i].w;
else return(P[i].d-3)*P[i].w;
}
void swap(int *a,int *b)
{
int t=*a;*a=*b;*b=t;
}
void Qsort(int *A,int start,int end)
{
int i=start,j=end,m=torque(A[start]);
do
{
while(torque(A[i])<m) i++;
while(torque(A[j])>m) j--;
if(i<=j)
{
swap(&A[i],&A[j]);
i++;
j--;
}
}while(i<=j);
if(i<end) Qsort(A,i,end);
if(j>start) Qsort(A,start,j);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("10123.txt","r",stdin);
#endif
int len,w,N=0;
while(scanf("%d%d%d",&len,&w,&n)==3 &&(len || w || n))
{
left=right=3*w;
int i;
for(i=0; i<n; i++)
{
scanf("%d%d",&P[i].d,&P[i].w);
P[i].d*=2;
}
printf("Case %d:\n",++N);
memset(vis,0,sizeof(vis));
int cur=0;
for(i=0;i<n;i++)
{
if(P[i].d<=3 && P[i].d>=-3)
{
left+=(P[i].d+3)*P[i].w;
right+=(3-P[i].d)*P[i].w;
vis[i]=true;
A[cur++]=i;
}
}
n1=n2=0;
for(i=0;i<n;i++) if(!vis[i])
{
if(P[i].d<0) L[n1++]=i;
else R[n2++]=i;
}
Qsort(L,0,n1-1);
Qsort(R,0,n2-1);
if(dfs(left,right,cur)==2)
{
for(i=n-1;i>=0;i--) printf("%d %d\n",P[A[i]].d/2,P[A[i]].w);
}else printf("Impossible\n");
}
return 0;
}