ABC Puzzle题解——DFS

D - ABC Puzzle 题解

这是一个大模拟的DFS题,写一下题解吧,目前只有我自己这个能理解

1.4种情况模拟,不选,选abc

2.剪枝,若单行内不满足有3个,剪掉

3.判断,先判断首字母,再判断重复,因为>3且无重复的话,就可以通过

#include <bits/stdc++.h>
using namespace std;
int n;
string a,b;
int ma[20][20];
int visx[100][100],visy[100][100],visx_first[100],visy_first[100];
bool out=0;
void check() {
    bool logo=false;
    memset(visx_first,0,sizeof(visx_first));
    memset(visy_first,0,sizeof(visy_first));
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {//横纵判断
            if (ma[i][j]!=0&&visx_first[i]==0) {
                visx_first[i]=ma[i][j];
            }
            if (ma[i][j]!=0&&visy_first[j]==0) {
                visy_first[j]=ma[i][j];
            }
            //用来存储首行内容
            if (visx[i][ma[i][j]]>1) {
                logo=true;
            }
            if (visy[j][ma[i][j]]>1) {
                logo=true;
            }//用来判断是否有重复
            if (visx[i][ma[i][j]]==0&&ma[i][j]!=0) {
                visx[i][ma[i][j]]++;
            }
            if (visy[j][ma[i][j]]==0&&ma[i][j]!=0) {
                visy[j][ma[i][j]]++;
            }//记录数据
        }
    }
    for(int i=1;i<=n;i++) {
        if (visx_first[i]!=a[i]-'A'+1) {
            logo=true;
        }
        if (visy_first[i]!=b[i]-'A'+1) {
            logo=true;
        }//看看首行首列是否相等
    }
    if (logo==0) {//无问题
        cout<<"Yes"<<endl;
        for (int i=1;i<=n;i++) {
            for (int j=1;j<=n;j++) {
                if (ma[i][j]==0) {
                    cout<<'.';
                }
                else {
                    cout<<char(ma[i][j]+'A'-1);
                }
            }
            cout<<endl;
        }
        exit(0);
    }
}
bool visabc[10][10], visabc1[10][10];
void dfs(int x,int y,int num) {
    if (y>n) {
        if (num<3) {//剪枝,若一行完了不够3个数,就不选了
            return;
        }
        dfs(x+1,1,0);
        return;
    }
    if (x>n) {
        check();
        return;
    }
    if (num<=3) {
        for (int i=1; i<=3; i++) {
            if (visabc[x][i]==0&&visabc1[y][i]==0) {//首行首列的字母i没用过
                visabc[x][i]=1;
                visabc1[y][i]=1;
                ma[x][y] = i;
                dfs(x,y+1,num+1);
                ma[x][y] = 0;
                visabc[x][i]=0;
                visabc1[y][i]=0;
            }
        }
    }
    dfs(x,y+1,num);
    return;
}
int main() {
    cin>>n;
    cin>>a>>b;
    a = ' '+a;
    b = ' '+b;//空出首位
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=n; j++) {
            ma[i][j] = 0;
        }
    }
    dfs(1,1,0);//1,1开始,选了0个
    if (out==0) {
        cout<<"No";
    }
    return 0;
}

本题两难点

1.剪枝考虑,若无num<3不录入,就会多很多判断与情况

2.判断模拟

posted @ 2025-07-20 12:00  Yuriha  阅读(42)  评论(0)    收藏  举报