虫食算

记下思路:
从后往前枚举,只要当前合法就加入,然后遇到不合法的就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时不能直接剪掉。因为还有可能当前的值就是正解,巨斧砍大树了。
写了整整一天了还没写完,扔着吧

/*
先生成全排列,打个暴力。只能拿20exit(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;//什么时候回溯字母? 
}
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值