其他分享
首页 > 其他分享> > 【DFS】Ybt_虫食算

【DFS】Ybt_虫食算

作者:互联网

题目大意

可恶的虫子把一些数字吃掉了!
你只能知道数位数和进制数为n的三个数 A,B,C。
其中 C=A+B,数字都由大写字母表示,相同字母表示这个位置上是相同的数字。
要你求每个字母所代表的数字。

输入

5
ABCED
BDACE
EBBAA

输出

1 0 3 4 2


深度搜索。枚举这些字母代表的数字。
从后往前枚举列,设这列的被加数,加数,与和为 a,b,c,得:

  1. 如果上一列的a’,b’确定,那么进位也是确定的,如果a+b+t不等于这一列的c,方案不合法
  2. 如果上一列不确定,如果 a+b不等于c 且 a+b+1不等于c,方案不合法
  3. 如果最大位有进位…方案不合法。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

bool used[30];
int n, flag, t;
int k[30],A[30],B[30],S[30],sssx[30];

char getc(){  //读入
	char lc = getchar();
	while(lc > 'Z' || lc < 'A') lc = getchar();
	return lc;
}

bool check(){  //判断
	int jw = 0;
	for(int i = n; i > 0; --i){
		int a = k[A[i]], b = k[B[i]], c = k[S[i]];
		if(a != -1 && b != -1 && c != -1){ //知道这三个数
			if(jw != -1){  //知道进位
				if((a+b+jw) % n != c) return 0;
				if(i == 1 && a+b+jw >= n) return 0;  //最大位超
				jw = (a+b+jw) / n;
			} 
			else{  //不知道进位
				if((a+b) % n != c && (a+b+1) % n !=c) return 0; 
				if(i == 1 && a+b >=n) return 0; //最大位超
			}
		}
		else jw = -1;
	}
	return 1;  //返回
}

void dfs(int noo){  //第几个该填的数的序号...
	if(noo == n){
		flag = 1;
		return;
	}
	int no = sssx[noo];  //no为该填的数
	for(int i = n-1; i >= 0; --i)  //倒着轮会快一点
	if(used[i] == 0){ //没填过
	    k[no] = i;
		if(check()){  //判断
	    	used[i] = 1;
	    	dfs(noo + 1);
	    	if(flag) return;
	    	used[i] = 0;
	    }
	    k[no] = -1;
	}
} 

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i) A[i] = getc()-65;
	for(int i = 1; i <= n; ++i) B[i] = getc()-65;
	for(int i = 1; i <= n; ++i) S[i] = getc()-65;
	for(int i = n; i >= 1; --i){  //搞个判断字母的顺序(从数位小到大)
		if(used[A[i]] == 0) sssx[t++] = A[i];
		used[A[i]] = 1;
		if(used[B[i]] == 0) sssx[t++] = B[i];
		used[B[i]] = 1;
		if(used[S[i]] == 0) sssx[t++] = S[i];
		used[S[i]] = 1;
	}
	memset(used, 0, sizeof(used));
	for(int i = 0; i < n; ++i) k[i] = -1; 
	dfs(0);
	for(int i = 0; i < n; ++i) //输出
	  printf("%d ", k[i]);
}

标签:used,return,食算,jw,Ybt,DFS,int,30,sssx
来源: https://blog.csdn.net/qq_42937087/article/details/112393825