【回溯】B030_LQ_机器人塔(枚举第一层+检查其它层 / 想成一维去做)

X星球的机器人表演拉拉队有两种服装,A和B。
他们这次表演的是搭机器人塔。类似:

     A
    B B
   A B A
  A A B B
 B B B A B
A B A B B A

队内的组塔规则是:

  • A 只能站在 AA 或 BB 的肩上。
  • B 只能站在 AB 或 BA 的肩上。

你的任务是帮助拉拉队计算一下,在给定A与B的人数时,可以组成多少种花样的塔。

输入一行两个整数 M 和 N,空格分开(0

要求输出一个整数,表示可以产生的花样种数。

用户输入:
1 2
程序应该输出:
3

用户输入:
3 3
程序应该输出:
4
方法一:枚举最后一层

思路

dfs 记录列数数,每次都确定好最后一层,如果最后一层是合法的,就一定能构造出一个机器人塔

#include
using namespace std;

const int N=550;
int dep, n, m, ans, H[N], cnt[2];
char A[N][N], alps[2]={'A', 'B'};
void sum2height() {
    int s=0;
    for(int i=1;i<=50;i++) {
        s+=i, H[i]=s;
    }
}
bool chk() {
    int ra=n, rb=m;
    for (int i=0; i<dep; i++) {
        if (A[dep-1][i]=='A') ra--;
        else                  rb--;
    }
    
    for (int i=dep-2; i>=0; i--)
    for (int j=0; j<=i; j++) {
        if (A[i+1][j] != A[i+1][j+1]) {
            if (--rb<0) return false;
            A[i][j]='B';
        } else {    
            if (--ra<0) return false;
            A[i][j]='A';
        }
    }
    return true;
}
void dfs(int c) {
    if (c==dep) {
        if (chk()) ans++;
        return;
    }
    for (int k=0; k<2; k++) if (cnt[k]) {
        cnt[k]--, A[dep-1][c]=alps[k];
        dfs(c+1);
        cnt[k]++;
    }
}
int main() {
    std::ios::sync_with_stdio(false);
    cin >> n >> m;
    sum2height();
    for (int i=0; ;i++) if (H[i] == n+m) {
        dep=i;
        break;
    }
    cnt[0]=n, cnt[1]=m;
    dfs(0);
    cout << ans;
    return 0;
}

可优化的地方是求高度那一块

这是转成一维做的大概的思路

int a[1100];
char s1[1000],s2[1000];
int cnt[1000];
int n,m,k,ans;
void init(){
    int sum=0;
    for(int i=1;i<=50;i++) {
        sum+=i; 
        a[i]=sum;
    }
}
int judge(int t) {//判断当前的状况是不是满足条件
    strcpy(s2+1,s1+1);
    int sum_a=0,sum_b=0;
    while(t--){
        for(int i=1;i<=t;i++) {
            if(s2[i]=='A')sum_a++;
            if(s2[i]=='B')sum_b++;
        }
        // 这一层的AB个数统计完后, 将这一层更新为下一层,继续统计 
        for(int i=1;i<=t-1;i++){
            if(s2[i]==s2[i+1])
                s2[i]='A';
            else
                s2[i]='B';
        }
    }
    if(sum_a==m&&sum_b==n)
        return 1;
    return 0;
}
void dfs(int cnt){
    if(cnt==k+1) {
        if(judge(k))
            ans++;
        return;
    }
    if(!cnt[cnt]){
        cnt[cnt]=1; s1[cnt]='A';
        dfs(cnt+1);
        s1[cnt]='B';
        dfs(cnt+1);
        cnt[cnt]=0;
    }
}

你可能感兴趣的:(#,【回溯】)