1、本题,很多人说是水题,我却WA了4次+TLE1次。
2、考察的就是队列+链表。本人一向对链表有恐惧心理,所以打算只用队列蒙混过关,下场是很悲惨的——毫无悬念地TLE了。
3、每堆纸牌可以用数组模拟,数组和数组之间可以用链表模拟,因为会出现空档,如果再搜索中还要处理空档,将会造成巨大的时间浪费。这里的链表不是很“纯正”,因为没有用指针,只用了两个数组left和right,但是还是用到了链式结构的思想——终于省出一大笔时间。
4、最后还是WA,抱着试试看的心理,在函数的&&后面添加了一个大括号,果断AC。原因就是我没有掌握好短路运算符。如果没有括号,那么虽然本意是当两张纸牌的花色相同时,就判断可以移动,但事实上,由于前面对已挪出的纸牌赋值成\0,造成两个都是\0的话也可以移动这种情况,就导致了错误。
5、感慨:AC和爱情一样,总在不经意间悄悄来临,让你措手不及却又欣喜若狂。
#include <stdio.h>
char s[60][110]={""};
int p,i,num[60]={0},flag=1,pile=0,left[60]={0},right[60]={0},temp;
void perform(int i,int j)
{
if(s[i][num[i]]&&(s[i][num[i]]==s[j][num[j]]||s[i][num[i]+1]==s[j][num[j]+1]))
{
num[j]+=2;
s[j][num[j]]=s[i][num[i]];
s[j][num[j]+1]=s[i][num[i]+1];
s[i][num[i]]=s[i][num[i]+1]='\0';
num[i]-=2;
if(num[i]==-2)
{
left[right[i]]=left[i];
right[left[i]]=right[i];
}
flag=1;
}
}
int main(void)
{
num[52]=-2;left[52]=51;left[51]=50;right[51]=52;
while(1)
{
p=0;pile=0;
while(scanf("%s",s[p])==1)
{
if(s[p][0]=='#'||p==51) break;
else
{
left[p]=p-1;
right[p]=p+1;
p++;
}
}
if(p==0) break;
flag=1;
while(flag)
{
flag=0;
perform(1,0);
if(flag) continue;
temp=left[2];
perform(2,temp);
if(flag) continue;
i=3;
while(i<52)
{
while(num[i]<0&&i<52) i++;
if(num[i]>=0)
{
temp=left[left[left[i]]];
perform(i,temp);
if(flag) break;
temp=left[i];
perform(i,temp);
if(flag) break;
}
if(i!=52)
i=right[i];
else
break;
}
}
for(i=0;i<52;i++)
if(num[i]>=0) pile++;
if(pile==1)
printf("%d pile remaining:",pile);
else
printf("%d piles remaining:",pile);
for(i=0;i<52;i++)
if(num[i]>=0)
{
printf(" %d",(num[i]+2)/2);
}
printf("\n");
memset(s,'\0',sizeof(s));
memset(num,0,sizeof(num));
memset(left,0,sizeof(left));
memset(right,0,sizeof(right));
num[52]=-2;left[52]=51;left[51]=50;right[51]=52;
}
return 0;
}