虽然是提交答案的题目,但还是硬着头皮做了一下,想法其实也不是我的,很老很老的某位神犇的题解
这题是一个双启发函数+随机搜索的题,看上去程序应该很慢,实际上竟然最大数据秒解,而且第一次运行就可找到比标准答案优的解,无不让人佩服(我是说佩服写题解的神犇)
贪心的想,每个小猪要飞向猪圈必定找最短路,那么每个小猪向当前所有猪圈连边,km算法最优匹配算权值作为当前操作的启发函数值,但是每一步都做km就会特慢,而且解的优劣也不理想,所以定义另一个启发函数F1表示做了当前操作后若往后不操作的情况下最后一个可以回猪圈的小猪所用时间T加上无论如何都不能回家的小猪个数m的平方的三倍
为什么这么定义函数呢?因为此神犇亲测多数函数后优选出来的。
那么,先计算F1,若F1一样,计算KM,若一样,随机选决策。
我只运行了一次,就有103分,多运行几次就会更优的。
奇丑代码,勿喷
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
typedef int arr[1005];
arr vili,link,vihe,head,vine,next,vitu,turn,vipx,px,vipy,py,vicx,vicy,vifo,foll,lx,ly,pre,slack;
int trap[205][205],w[1005][1005];
int n=0,nop=0,maint=0,tott=0,noc=0;
bool changeflag=0;
int f1[205][10];
bool vx[1005],vy[1005];
bool downdate(int &a,int b)
{
if (a>b) {a=b;return 1;}
return 0;
}
void update(int &a,int b)
{
if (a<b) a=b;
}
void changevi(int l,int t)
{
int ne=vine[0];
while (ne)
{
if (t==2||t==8)
{
if (vipx[ne]==l)
vitu[ne]=t;
}
else
{
if (vipy[ne]==l)
vitu[ne]=t;
}
ne=vine[ne];
}
}
void changemain(int l,int t)
{
int ne=next[0];
while (ne)
{
if (t==2||t==8)
{
if (px[ne]==l)
turn[ne]=t;
}
else
{
if (py[ne]==l)
turn[ne]=t;
}
ne=next[ne];
}
}
void movevi(int &nop)
{
int ne=vine[0],nowp=0,temp=0;
while (ne)
{
if (vitu[ne]==6)
{
vipx[ne]++;
if (vipx[ne]>n) vipx[ne]=1;
nowp=trap[vipx[ne]][vipy[ne]];
if (nowp!=0)
if (vifo[0]==nowp||vili[nowp]!=0)
{
nop--;
vifo[vili[nowp]]=vifo[nowp];
vili[vifo[nowp]]=vili[nowp];
vili[nowp]=0;
vifo[nowp]=0;
vine[vihe[ne]]=vine[ne];
vihe[vine[ne]]=vihe[ne];
temp=vihe[ne];
vine[ne]=0;
vihe[ne]=0;
ne=temp;
}
}
else
if (vitu[ne]==4)
{
vipx[ne]--;
if (vipx[ne]<=0) vipx[ne]=n;
nowp=trap[vipx[ne]][vipy[ne]];
if (nowp!=0)
if (vifo[0]==nowp||vili[nowp]!=0)
{
nop--;
vifo[vili[nowp]]=vifo[nowp];
vili[vifo[nowp]]=vili[nowp];
vili[nowp]=0;
vifo[nowp]=0;
vine[vihe[ne]]=vine[ne];
vihe[vine[ne]]=vihe[ne];
temp=vihe[ne];
vine[ne]=0;
vihe[ne]=0;
ne=temp;
}
}
else
if (vitu[ne]==8)
{
vipy[ne]--;
if (vipy[ne]<=0) vipy[ne]=n;
nowp=trap[vipx[ne]][vipy[ne]];
if (nowp!=0)
if (vifo[0]==nowp||vili[nowp]!=0)
{
nop--;
vifo[vili[nowp]]=vifo[nowp];
vili[vifo[nowp]]=vili[nowp];
vili[nowp]=0;
vifo[nowp]=0;
vine[vihe[ne]]=vine[ne];
vihe[vine[ne]]=vihe[ne];
temp=vihe[ne];
vine[ne]=0;
vihe[ne]=0;
ne=temp;
}
}
else
if (vitu[ne]!=5)
{
vipy[ne]++;
if (vipy[ne]>n) vipy[ne]=1;
nowp=trap[vipx[ne]][vipy[ne]];
if (nowp!=0)
if (vifo[0]==nowp||vili[nowp]!=0)
{
nop--;
vifo[vili[nowp]]=vifo[nowp];
vili[vifo[nowp]]=vili[nowp];
vili[nowp]=0;
vifo[nowp]=0;
vine[vihe[ne]]=vine[ne];
vihe[vine[ne]]=vihe[ne];
temp=vihe[ne];
vine[ne]=0;
vihe[ne]=0;
ne=temp;
}
}
ne=vine[ne];
}
}
void movemain(int &nop)
{
int ne=next[0],nowp=0,temp=0;
while (ne)
{
if (turn[ne]==6)
{
px[ne]++;
if (px[ne]>n) px[ne]=1;
nowp=trap[px[ne]][py[ne]];
if (nowp!=0)
if (foll[0]==nowp||link[nowp]!=0)
{
nop--;
foll[link[nowp]]=foll[nowp];
link[foll[nowp]]=link[nowp];
link[nowp]=0;
foll[nowp]=0;
next[head[ne]]=next[ne];
head[next[ne]]=head[ne];
temp=head[ne];
next[ne]=0;
head[ne]=0;
ne=temp;
tott+=maint;
}
}
else
if (turn[ne]==4)
{
px[ne]--;
if (px[ne]<=0) px[ne]=n;
nowp=trap[px[ne]][py[ne]];
if (nowp!=0)
if (foll[0]==nowp||link[nowp]!=0)
{
nop--;
foll[link[nowp]]=foll[nowp];
link[foll[nowp]]=link[nowp];
link[nowp]=0;
foll[nowp]=0;
next[head[ne]]=next[ne];
head[next[ne]]=head[ne];
temp=head[ne];
next[ne]=0;
head[ne]=0;
ne=temp;
tott+=maint;
}
}
else
if (turn[ne]==8)
{
py[ne]--;
if (py[ne]<=0) py[ne]=n;
nowp=trap[px[ne]][py[ne]];
if (nowp!=0)
if (foll[0]==nowp||link[nowp]!=0)
{
nop--;
foll[link[nowp]]=foll[nowp];
link[foll[nowp]]=link[nowp];
link[nowp]=0;
foll[nowp]=0;
next[head[ne]]=next[ne];
head[next[ne]]=head[ne];
temp=head[ne];
next[ne]=0;
head[ne]=0;
ne=temp;
tott+=maint;
}
}
else
if (turn[ne]!=5)
{
py[ne]++;
if (py[ne]>n) py[ne]=1;
nowp=trap[px[ne]][py[ne]];
if (nowp!=0)
if (foll[0]==nowp||link[nowp]!=0)
{
nop--;
foll[link[nowp]]=foll[nowp];
link[foll[nowp]]=link[nowp];
link[nowp]=0;
foll[nowp]=0;
next[head[ne]]=next[ne];
head[next[ne]]=head[ne];
temp=head[ne];
next[ne]=0;
head[ne]=0;
ne=temp;
tott+=maint;
}
}
ne=next[ne];
}
}
bool find(int x,int n)
{
if (vx[x]) return 0;
vx[x]=1;
int i=0,tmp=0;
for (i=1;i<=n;i++)
{
tmp=lx[x]+ly[i]-w[x][i];
if (!vy[i] && tmp==0)
{
vy[i]=1;
if (pre[i]==0 || find(pre[i],n))
{
pre[i]=x;
return 1;
}
}
else
downdate(slack[i],tmp);
}
return 0;
}
int km(int n)
{
int k=0,d=0,i=0,j=0;
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(pre,0,sizeof(pre));
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
update(lx[i],w[i][j]);
}
for (k=1;k<=n;k++)
while (1)
{
memset(vx,0,sizeof(vx));
memset(vy,0,sizeof(vy));
memset(slack,60,sizeof(slack));
vx[0]=1;
if (find(k,n)) break;
d=400;
for (i=1;i<=n;i++)
if (!vy[i]) downdate(d,slack[i]);
for (i=1;i<=n;i++)
{
if (vx[i]) lx[i]-=d;
if (vy[i]) ly[i]+=d; else slack[i]-=d;
}
}
int tot=0;
for (i=1;i<=n;i++)
tot+=w[pre[i]][i];
return tot;
}
void build()
{
int ne=vine[0],me=0,nowx=0,nowy=0,tmpw=0,tmpx=0,tmpy=0,tmp=0;
while (ne)
{
++nowx;
me=vifo[0];
nowy=0;
while (me)
{
++nowy;
tmpx=abs(vicx[me]-vipx[ne]);
downdate(tmpx,abs(vicx[me]+n-vipx[ne]));
downdate(tmpx,abs(-vicx[me]+n+vipx[ne]));
tmpy=abs(vicy[me]-vipy[ne]);
downdate(tmpy,abs(vicy[me]+n-vipy[ne]));
downdate(tmpy,abs(-vicy[me]+n+vipy[ne]));
tmpw=tmpx+tmpy;
if (vitu[ne]==2)
if (vicy[me]>=vipy[ne])
tmpw=tmpx+abs(vicy[me]-vipy[ne]);
else
tmpw=tmpx+abs(n-vipy[ne]+vicy[me]);
else
if (vitu[ne]==8)
if (vicy[me]<=vipy[ne])
tmpw=tmpx+abs(vicy[me]-vipy[ne]);
else
tmpw=tmpx+abs(n+vipy[ne]-vicy[me]);
else
if (vitu[ne]==6)
if (vicx[me]>=vipx[ne])
tmpw=tmpy+abs(vicx[me]-vipx[ne]);
else
tmpw=tmpy+abs(n-vipx[ne]+vicx[me]);
else
if (vitu[ne]==4)
if (vicx[me]<=vipx[ne])
tmpw=tmpy+abs(vipx[ne]-vicx[me]);
else
tmpw=tmpy+abs(vipx[ne]+n-vicx[me]);
w[nowx][nowy]=400-tmpw;
me=vifo[me];
}
ne=vine[ne];
}
}
int evaf1(int l,int t)
{
if (changeflag)
{
memcpy(vihe,head,sizeof(head));
memcpy(vili,link,sizeof(link));
memcpy(vifo,foll,sizeof(foll));
memcpy(vine,next,sizeof(next));
}
memcpy(vitu,turn,sizeof(turn));
memcpy(vipx,px,sizeof(px));
memcpy(vipy,py,sizeof(py));
changeflag=0;
int nums=nop,orn=nop,i=0,val=0;
if (t!=5) changevi(l,t);
for (i=1;i<=n;i++)
{
movevi(nums);
if (nums<orn)
{
val=i;
orn=nums;
changeflag=1;
}
}
val+=(3*nums*nums);
return val;
}
int evaf2(int l,int t)
{
if (changeflag)
{
memcpy(vihe,head,sizeof(head));
memcpy(vili,link,sizeof(link));
memcpy(vifo,foll,sizeof(foll));
memcpy(vine,next,sizeof(next));
}
memcpy(vitu,turn,sizeof(turn));
memcpy(vipx,px,sizeof(px));
memcpy(vipy,py,sizeof(py));
changeflag=0;
if (t!=5) changevi(l,t);
int nums=nop;
movevi(nums);
if (nums<nop) changeflag=1;
build();
return km(nums);
}
void print(int dec1,int dec2)
{
if (dec2==5)
printf("X0");
else
if (dec2==2)
printf("S%d",dec1-1);
else
if (dec2==8)
printf("N%d",dec1-1);
else
if (dec2==4)
printf("W%d",dec1-1);
else
printf("E%d",dec1-1);
printf("\n");
}
int main(int argc,char* argv[])
{
char inname[200],outname[200];
srand((unsigned)time(NULL));
sprintf(inname,"airpig%s.in",argv[1]);
sprintf(outname,"airpig%s.out",argv[1]);
freopen(inname,"r",stdin);
freopen(outname,"w",stdout);
int i=0,j=0;
scanf("%d",&n);
printf("%d\n",n);
scanf("%d\n",&n);
char tmpc=0;
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++)
{
tmpc=getchar();
if (tmpc!='*'&&tmpc!='.')
{
nop++;
head[nop]=nop-1;
next[nop-1]=nop;
px[nop]=j;
py[nop]=i;
turn[nop]=(int)(tmpc-'0');
}
else
if (tmpc=='*')
{
noc++;
link[noc]=noc-1;
foll[noc-1]=noc;
vicx[noc]=j;
vicy[noc]=i;
trap[j][i]=noc;
}
}
scanf("\n");
}
int ans1=0,ans2=0,dec1=0,dec2=0,tmp=0;
while (nop)
{
changeflag=1;
ans1=evaf1(0,5);
ans2=200000000;
dec1=0;
dec2=5;
for (i=1;i<=n;i++)
{
f1[i][2]=evaf1(i,2);
f1[i][8]=evaf1(i,8);
f1[i][4]=evaf1(i,4);
f1[i][6]=evaf1(i,6);
if (downdate(ans1,f1[i][2]))
{
dec1=i;
dec2=2;
}
if (downdate(ans1,f1[i][8]))
{
dec1=i;
dec2=8;
}
if (downdate(ans1,f1[i][4]))
{
dec1=i;
dec2=4;
}
if (downdate(ans1,f1[i][6]))
{
dec1=i;
dec2=6;
}
}//选最优的ans1
changeflag=1;
ans2=evaf2(dec1,dec2);//计算当前决策的f2,注意dec2=5时的情况
for (i=1;i<=n;i++)
{
if (ans1==f1[i][2] &&(dec1!=i || dec2!=2))
{
tmp=evaf2(i,2);
if (tmp>ans2)
{
ans2=tmp;
dec1=i;
dec2=2;
}
else
if (tmp==ans2 &&(rand()&1))
{
ans2=tmp;
dec1=i;
dec2=2;
}
}
if (ans1==f1[i][8] &&(dec1!=i || dec2!=8))
{
tmp=evaf2(i,8);
if (tmp>ans2)
{
ans2=tmp;
dec1=i;
dec2=8;
}
else
if (tmp==ans2 &&(rand()&1))
{
ans2=tmp;
dec1=i;
dec2=8;
}
}
if (ans1==f1[i][4] &&(dec1!=i || dec2!=4))
{
tmp=evaf2(i,4);
if (tmp>ans2)
{
ans2=tmp;
dec1=i;
dec2=4;
}
else
if (tmp==ans2 &&(rand()&1))
{
ans2=tmp;
dec1=i;
dec2=4;
}
}
if (ans1==f1[i][6] &&(dec1!=i || dec2!=6))
{
tmp=evaf2(i,6);
if (tmp>ans2)
{
ans2=tmp;
dec1=i;
dec2=6;
}
else
if (tmp==ans2 &&(rand()&1))
{
ans2=tmp;
dec1=i;
dec2=6;
}
}
}//选最优的ans2
if (dec2!=5) changemain(dec1,dec2);//按决策改变原图中的小猪的转向,注意dec2==5的情况
maint++;
movemain(nop);//按当前状态运行一步
print(dec1,dec2);//打印决策
}
printf("%d %d",maint,tott);
return 0;
}