【ABC166F】题解

题目传送门

题解

对于每次操作,只需要修改两个数,自然会想到 dfs 枚举每次操作修改哪两个数,但是题目不允许你这么做,因为时间复杂度是 $2^n$,而 $n \le 10^5$,直接写会炸掉。

但是我们可以使用一种叫做《搜索剪枝》的神奇东西。

这题的剪枝是一种可行性剪枝,判断每个数是否合法,如果不合法直接退出。

if (k[0] < 0 || k[1] < 0 || k[2] < 0){
    return;
}

dfs

// k[0],k[1],k[2] 分别代表 A,B,C
void dfs(int x){
    if (k[0] < 0 || k[1] < 0 || k[2] < 0){
        return;
    }
    if (x > n){
        cout << "Yes\n";
        for (int i = 1; i <= n; i++){
            cout << s[i][a[i]] << '\n';
        }
        exit(0);
    }
    for (int i = 0; i < 2; i++){
        a[x] = i;
        k[s[x][i] - 'A']++;
        k[s[x][!i] - 'A']--;
        dfs(x + 1);
        k[s[x][i] - 'A']--;
        k[s[x][!i] - 'A']++;
    }
}

AC Code

#include<iostream>

using namespace std;

const int MAXN = 1e5 + 10;

int n,k[3],a[MAXN];
string s[MAXN];

// k[0],k[1],k[2] 分别代表 A,B,C
void dfs(int x){
    if (k[0] < 0 || k[1] < 0 || k[2] < 0){
        return;
    }
    if (x > n){
        cout << "Yes\n";
        for (int i = 1; i <= n; i++){
            cout << s[i][a[i]] << '\n';
        }
        exit(0);
    }
    for (int i = 0; i < 2; i++){
        a[x] = i;
        k[s[x][i] - 'A']++;
        k[s[x][!i] - 'A']--;
        dfs(x + 1);
        k[s[x][i] - 'A']--;
        k[s[x][!i] - 'A']++;
    }
}

int main(){
    cin >> n;
    for (int i = 0; i < 3; i++){
        cin >> k[i];
    }
    for (int i = 1; i <= n; i++){
        cin >> s[i];
    }
    dfs(1);
    cout << "No";
    return 0;
}

但这么写能 AC,仅仅只是因为数据太水了(正解 DP)

posted @ 2023-09-03 19:10  rksm2333  阅读(21)  评论(0)    收藏  举报  来源