这是一道很好的题目,教给了我很多暴力的剪枝方法
超链接不解释。。。。
https://www.luogu.org/problem/show?pid=1092
解释:
重构了两遍代码才A掉的,当时思路真的有问题,没办法剪枝和处理进位情况,读了一个题解描述。
好了正题
整体思路是从后向前,从上向下的依次搜索三个大数据
几个相当重要且有趣的剪枝+思路:
1.每次搜完就判断是否已经有不合法情况出现:一列三个已知不合法,例如1+1=3;已知两个数未知进位 但 进不进 都不可以满足就不合法;一列已知两个数以及进位计算后不合法。这三种情况直接return
2.重新整理一遍进位
3.在搜一个数时如果所有情况都失败则return;
4.一列已知两个数及进位情况就直接算第三个数 !!且不满足时直接return!!
5.如果不满足3.4,孩子老老实实搜吧,但是从后面往前搜会快哦
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
bool ff=false,d[30];
int map[4][30],jw[30];
int n,r[30];
bool pd()
{
int add=0,i;
for (i=n;i>=1;i--)
{
if (r[map[1][i]]!=-1 && r[map[2][i]]!=-1 && r[map[3][i]]!=-1)
{
if (add==-1 && (r[map[1][i]]+r[map[2][i]])%n!=r[map[3][i]] && (r[map[1][i]]+r[map[2][i]]+1)%n!=r[map[3][i]])//没有已知进位
return false;
if (add!=-1)
if ((r[map[1][i]]+r[map[2][i]]+add)%n!=r[map[3][i]]) return false;//有已知进位
else add=(r[map[1][i]]+r[map[2][i]]+add)/n;
}
else add=-1;
}
return true;
}
int find(int i,int j)//有没有知二求三 或者是 直接不合法
{
if(j==1)
{
if (r[map[2][i]]!=-1 && r[map[3][i]]!=-1)
{
int quq=(r[map[3][i]]-r[map[2][i]]+n)%n;
if(jw[i+1]==1) quq=(quq-1+n)%n;
if (d[quq]) return -2;
else return quq;
}
return -1;
}
else
if (j==2)
{
if (r[map[1][i]]!=-1 && r[map[3][i]]!=-1)
{
int quq=(r[map[3][i]]-r[map[1][i]]+n)%n;
if(jw[i+1]==1) quq=(quq-1+n)%n;
if (d[quq]) return -2;
else return quq;
}
return -1;
}
else
{
if (r[map[1][i]]!=-1 && r[map[2][i]]!=-1)
{
int quq=(r[map[2][i]]+r[map[1][i]])%n;
if(jw[i+1]==1) quq=(quq+1)%n;
if (d[quq]) return -2;
else return quq;
}
return -1;
}
}
void gx()//重新整理进位
{
int i;
for (i=n;i>=1;i--)
if (r[map[1][i]]!=-1 && r[map[2][i]]!=-1 && jw[i+1]!=-1)
if (r[map[1][i]]+r[map[2][i]]+jw[i+1]>=n) jw[i]=1; else jw[i]=0;
else return;
}
void dfs(int t,int x)
{
if (ff) return;
int i,j,k;
if (!pd()) return;
gx();
if (t==0)
{
ff=true;
for (i=1;i<=n-1;i++)
printf("%d ",r[i]);
printf("%d ",r[i]);
return;
}
for (k=x;k>=1;k--)
for (j=1;j<=3;j++)
if (r[map[j][k]]==-1)
{
int tmp=find(k,j);
if (tmp==-1)
{
for (i=0;i<=n-1;i++)
if (!d[i] && !ff)
{
d[i]=true;
r[map[j][k]]=i;
dfs(t-1,k);
d[i]=false;
r[map[j][k]]=-1;
}
return;
}
else if (tmp==-2) return;
else
{
d[tmp]=true;
r[map[j][k]]=tmp;
dfs(t-1,k);
d[tmp]=false;
r[map[j][k]]=-1;
return;
}
}
}
int main()
{
int j;char l;
scanf("%d\n",&n);
for (j=1;j<=n;j++)
{
scanf("%c",&l);
map[1][j]=l-'A'+1;
}
scanf("%d\n");
for (j=1;j<=n;j++)
{
scanf("%c",&l);
map[2][j]=l-'A'+1;
}
scanf("%d\n");
for (j=1;j<=n;j++)
{
scanf("%c",&l);
map[3][j]=l-'A'+1;
}
memset(d,0,sizeof(d));
memset(r,-1,sizeof(r));
memset(jw,-1,sizeof(jw));
jw[n+1]=0;
dfs(n,n);
}