P1092 虫食算(dfs+剪枝)

在这里插入图片描述
在这里插入图片描述
这道题多半一想就是dfs,但是有26总字母,所以如果按照先赋值完每个字母之后再去判断是否和答案相等,那么时间复杂度就是o(n!)了,早就超时了;所以这个题需要剪枝,但是这个题我感觉dfs过也都是巧合。。。。。。。。
为什么?因为按照枚举dfs赋值也有可能TLE,所以这道题dfs应该不是正解。但是dfs如果运气好也能刚好过;
我用的数组来映射+一个进位判断+字符串转化为数字的技巧AC的;
我用的dfs:
AC代码:

#include<bits/stdc++.h>
using namespace std;
int a[30],b[30],c[30];//把字符串转化为数字  
int ans[30];
int alp[30];//字母对应的值 
int re[100];//去重后,看一共有多少个不同的字母 
int n;
char s[3][1000];
int book[30];
int book2[30];
void dfs(int num){
    
    
	if(alp[a[0]]+alp[b[0]]>=n)return;//最高位不能有进位
	int jinwei=0;
	int j=0;
	for(int i=n-1,k=n-1;i>=0;i--,k--){
    
    
		  //如果还没有赋值完,那么剪枝
		  if(alp[a[i]]==-1||alp[b[i]]==-1||alp[c[i]]==-1)continue ;
		  if((alp[a[i]]+alp[b[i]]+1)%n!=alp[c[i]]&&(alp[a[i]]+alp[b[i]])%n!=alp[c[i]])//因为这个位 只有这两种情况,要么接受来自低位的进位1,那么就没有接受
		  {
    
    
		  	return ;
		   } 
		   ans[j++]=(alp[a[k]]+alp[b[k]]+jinwei)%n;//倒起来放入ans数组中 
		   jinwei=(alp[a[k]]+alp[b[k]]+jinwei)/n;
	}
	if(num==n){
    
    
		for(int i=0;i<n;i++){
    
    
			 if(ans[i]!=alp[c[n-i-1]])return ;
		}
		for(int i=0;i<n;i++)printf("%d%c",alp[i],i==n-1?'\n':' ');
		exit(0);
	} 
	  for(int i=n-1;i>=0;i--){
    
    
	  	  if(!book2[i]){
    
    
	  	  	    book2[i]=1;
	  	  	    alp[re[num]]=i;
	  	  	    dfs(num+1);
	  	  	    book2[i]=0;
	  	  	    alp[re[num]]=-1;//取消标记 
			}
	  }
}
int main(){
    
    
	scanf("%d",&n);
	scanf("%s%s%s",&s[0],&s[1],&s[2]);
	for(int i=0;i<n;i++){
    
    //把字母转化为数字 
		a[i]=s[0][i]-'A';
		b[i]=s[1][i]-'A';
		c[i]=s[2][i]-'A';
	}
	int g=0;
	for(int i=n-1;i>=0;i--){
    
    //去重 
		if(!book[a[i]]){
    
    
			re[g++]=a[i];
			book[a[i]]=1;
		}
		if(!book[b[i]]){
    
    
			re[g++]=b[i];
			book[b[i]]=1;
		}
		if(!book[c[i]]){
    
    
			re[g++]=c[i];
			book[c[i]]=1;
		}
	}
	for(int i=0;i<26;i++){
    
    
		 alp[i]=-1;
	}
	dfs(0);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_44555205/article/details/104128681