题目大意:有一排n枚硬币,一开始均正面朝上,每一次操作,你可以将任意n-1枚硬币进行翻转,现请你用最少的操作,将这n枚硬币翻转到一个指定的状态。
这道题主要就是宽搜,代码和注释如下,其实这道题最重要的就是father结点怎么去枚举之前的状态,我的做法是用一个father结点去枚举之前的状态。
代码如下!!!
#include<cstdio>
#include<cstring>
using namespace std;
bool b[110000];
int n;
struct node
{
int a[30],dep,fa;
}list[210000];
int kangtuo(node tno)//CLT传说中的判重,miao??
{
int ans=0;
for(int i=1;i<=n;i++) ans=ans*2+tno.a[i];
return ans;
}
int main()
{
memset(b,false,sizeof(b));
scanf("%d",&n);
char ss[1100];
scanf("%s",ss+1);
for(int i=1;i<=n;i++)//list[1]表示初始状态,list[0]表示结束状态
{
list[1].a[i]=0;
if(ss[i]=='1') list[0].a[i]=1;
else list[0].a[i]=0;
}
int bz=kangtuo(list[0]);
int head=1,tail=1;
b[kangtuo(list[1])]=true;//首先将初始状态标记
while(head<=tail)
{
for(int j=1;j<=n;j++)
{
node tno=list[head];
for(int k=1;k<=n;k++)
{//每次都是n-1枚硬币翻转,所以我们只要判断这枚硬币在这个状态时我们有没有翻过即可
if(j!=k)
{
if(tno.a[k]==1) tno.a[k]=0;
else tno.a[k]=1;//翻转过程
}
}
int kk=kangtuo(tno);//判重
if(b[kk]==false)//b数组表示我这个状态有没有进行过
{
b[kk]=true;
tno.dep++;//表示深度
tno.fa=head;//这个表示我上层的father结点是用的哪个状态,用来输出用
list[++tail]=tno;//存入
if(kk==bz) //如果当前状态和目标状态是否相等。
{
printf("%d\n",tno.dep);//输出深度
int len=1,ttt[1000];ttt[len]=tail;
while(ttt[len]!=1)//ttt是来储存我之前的状态的所达成的父亲状态
{
ttt[len+1]=list[ttt[len]].fa;
len++;
}
for(int i=len-1;i>=1;i--)//程序再见!!
{
for(int t=1;t<=n;t++)printf("%d",list[ttt[i]].a[t]);
printf("\n");
}
return 0;
}
}
}
head++;
}
}
特别声明:本蒟蒻禁止侵权抄袭!!!!