记下思路:
从后往前枚举,只要当前合法就加入,然后遇到不合法的就return;
深搜应该是保存完了当前状态,把下一个状态传进去吧。
1)进位一定要进到num-1上,而不是num
2)如果该数字出现过直接return 这个条件漏了
3)还有b[ans[ch1[num]-‘A’+1]==1 return;标记每个数字漏了 如果该数字出现过直接return
4)&&写成了&也是我干出来的
5)更新2时,如果ans[ch2[num]-‘A’+1]!=-1时不能直接剪掉。因为还有可能当前的值就是正解,巨斧砍大树了。
写了整整一天了还没写完,扔着吧
/*
先生成全排列,打个暴力。只能拿20分 exit(0)30分
考虑一下优化
那就换一种搜索的思路,纵向枚举,一旦遇到不符合的情况就回溯。
但是还要考虑进位的问题 就用一个数组来保存
应该会剪枝不少吧
放数可能的情况:
1、两个都确定
2、都不确定
3、一个确定一个不确定
又写残了个dfs
之前一直不能解决的问题:
什么时候往哪里放哪个数,这时应该dfs加上一个参数 x记录当前行
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int n,ans[101],jw[101];//ans对应关系 jw保存进位
bool b[101];
char ch1[101],ch2[101],ch3[101];
void shuchu()
{
for (int i=1; i<=n; i++)
printf("%d ",ans[i]); printf("\n");
}
//ans 结果的对应关系
void dfs(int x,int num)//当前的位数num 选x行
{
if (num==0) {shuchu(); exit(0);}
printf("%d %d\n",x,num);
for (int i=1; i<=n; i++) printf("%d ",ans[i]); printf("\n");
if (ans[ch1[num]-'A'+1]!=-1&&ans[ch2[num]-'A'+1]!=-1&&ans[ch3[num]-'A'+1]!=-1)
{
int tmp=ans[ch1[num]-'A'+1]+ans[ch2[num]-'A'+1]+jw[num];
if (ans[ch3[num]-'A'+1]!=tmp%n) return;
if (tmp>=n) jw[num]=tmp/n;
dfs(1,num-1);
}
else if (x==3&&ans[ch1[num]-'A'+1]!=-1&&ans[ch2[num]-'A'+1]!=-1)
{//1 2-->3
int tmp=ans[ch1[num]-'A'+1]+ans[ch2[num]-'A'+1]+jw[num];
if (b[tmp%n]) return;//这个条件不能少
if (ans[ch3[num]-'A'+1]=tmp%n||ans[ch3[num]-'A'+1]==-1)
ans[ch3[num]-'A'+1]=tmp%n;
else return;
b[ans[ch3[num]-'A'+1]]=true;
if (tmp>=n) jw[num-1]=tmp/n;
dfs(1,num-1);
b[ans[ch3[num]-'A'+1]]=false;
ans[ch3[num]-'A'+1]=-1;
jw[num-1]=0;//进位需要回溯吗?
}
else if (x==1&&ans[ch1[num]-'A'+1]==-1&&ans[ch2[num]-'A'+1]!=-1)
{//2 3-->1
int tmp=ans[ch3[num]-'A'+1]-ans[ch2[num]-'A'+1]-jw[num];
if (b[(tmp+n)%n]) return;
if (ans[ch1[num]-'A'+1]=tmp%n||ans[ch1[num]-'A'+1]==-1)
ans[ch1[num]-'A'+1]=tmp%n;
else return;
b[ans[ch1[num]-'A'+1]]=true;
if (tmp<0) jw[num-1]=1;//进位只有可能是1
dfs(1,num-1);
b[ans[ch1[num]-'A'+1]]=false;
ans[ch1[num]-'A'+1]=-1;
jw[num-1]=0;//进位需要回溯吗?
}
else if (x==2&&ans[ch1[num]-'A'+1]!=-1&&ans[ch2[num]-'A'+1]==-1&&ans[ch3[num]-'A'+1]!=-1)
{//1 3-->2
int tmp=ans[ch3[num]-'A'+1]-ans[ch1[num]-'A'+1]-jw[num];
if (b[(tmp+n)%n]) return;
if (ans[ch2[num]-'A'+1]=tmp%n||ans[ch2[num]-'A'+1]==-1)
ans[ch2[num]-'A'+1]=tmp%n;
else return;
b[ans[ch2[num]-'A'+1]]=true;
if (tmp<0) jw[num-1]=1;
dfs(1,num-1);
b[ans[ch2[num]-'A'+1]]=false;
ans[ch2[num]-'A'+1]=-1;
jw[num-1]=0;//进位需要回溯吗?
}
else if (x==1&&ans[ch1[num]-'A'+1]!=-1) dfs(2,num);//如果这个字母已经有值了 就直接搜索
else if (x==2&&ans[ch2[num]-'A'+1]!=-1) dfs(3,num);
else if (x==3&&ans[ch3[num]-'A'+1]!=-1) dfs(1,num-1);
else
for (int i=n-1; i>=1; i--)
if (!b[i])
{
b[i]=true;
if (x==1)
{
ans[ch1[num]-'A'+1]=i;
dfs(2,num);
ans[ch1[num]-'A'+1]=-1;
}
if (x==2)
{
ans[ch2[num]-'A'+1]=i;
dfs(3,num);
ans[ch2[num]-'A'+1]=-1;
}
if (x==3)
{
ans[ch3[num]-'A'+1]=i;
dfs(1,num-1);
ans[ch3[num]-'A'+1]=-1;
}
b[i]=false;
}
}
int main()
{
scanf("%d",&n);
scanf("%s%s%s",ch1+1,ch2+1,ch3+1);
for (int i=0; i<=n; i++) ans[i]=-1;
dfs(1,n);
return 0;
}
/*
8
ABDEBEHG
FGDBBAGB
EDEDCHGE
2 1 3 7 6 4 5 0
21
BADCEFGHIJKLMNOPQRSTU
BADCEFGHIJKLMNOPQRSTU
BDEGIKMOQTBDEGIKMOQST
1 0 3 2 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
5
ABCED
BDACE
EBBAA
1 0 3 4 2
//ans 结果的对应关系
void dfs(int x,int y,int num)//当前的位数num 选x y是否可行
{
if (num==0) {shuchu(); exit(0);}
if (x==y&&ch1[num]!=ch2[num]) return;//不要忘记这种情况
if (ans[ch1[num]-'A'+1]!=-1&&ans[ch1[num]-'A'+1]!=x) return;//把不可放的情况都剪掉
if (ans[ch2[num]-'A'+1]!=-1&&ans[ch2[num]-'A'+1]!=y) return;
int tmp=x+y+jw[num];//不要忘记进位
if (ans[ch3[num]-'A'+1]!=-1&&ans[ch3[num]-'A'+1]!=tmp%n) return;
for (int i=1; i<=n; i++) printf("%d ",ans[i]); printf("\n");
b[x]=true; b[y]=true;//标记
ans[ch1[num]-'A'+1]=x; ans[ch2[num]-'A'+1]=y;
ans[ch3[num]-'A'+1]=tmp%n;
if (tmp>=n) jw[num-1]=tmp/n;
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
if (!b[i]&&!b[j])
{
dfs(i,j,num-1);
b[i]=false; b[j]=false;
}
ans[ch1[num]-'A'+1]=-1; ans[ch2[num]-'A'+1]=-1;//什么时候回溯字母?
}
*/