题意:
每组测试数据输入一个值n,对于每一个测试数据:
你要从0~9中取数给abcde和fghij每个字母赋值(每个数字用且只能用一次),形成两个数abcde和fghij,如果满足abcde / fghij = n,则按格式 xxxxx /xxxxx = n 输出所有可能情况(前导0允许存在而且需要输出);如果没有满足条件的情况则输出相应语句;
思路:
【两眼一闭写暴力】
穷举所有可能的情况有 10! 这样一个数量级,只列举abcde,另一个数可以求出来,然后看符不符合条件。
然后要注意的就是dfs写的方法,脑子里要有一层一层的调用栈
1. 到什么时候结束递归调用-递归出口
2. 如何穷举其他情况(或者说转移状态):for循环/取还是不取(for循环的一个灵活运用就是穷举不同的数列的时候,随着调用栈的层层深入,取的值的是按从左到右每个位置取出来的。因此在同一个for循环当中,穷举的是同一个位置的取值,所以为了不影响回溯,在递归调用完一级的dfs函数时,需要将标记的vis[]数组改回没有标记的状态)
#include <iostream>
#include <cstring>
using namespace std;
int n,vis[10],k=0;
bool flag=false;
void print(int a){
flag=true;
if(a/10000!=0) cout<<a*n<<' '<<'/'<<' '<<a<<' '<<'='<<' '<<n<<endl;
else cout<<a*n<<' '<<'/'<<' '<<0<<a<<' '<<'='<<' '<<n<<endl;
}
void dfs(int sum,int cnt){
if(cnt==5){
//cout<<sum<<endl;
int tmp=sum*n;
if(tmp/10000<=9 && tmp/10000>=1){ //保证是5位数再判断(不可能有先导零)
bool f=true;
//防止对回溯产生影响
int vis1[10];
for(int i=0;i<10;i++){
vis1[i]=vis[i];
}
while(tmp){ //判断这五位数是否是没有用过
if(vis1[tmp%10]==1) {
//cout<<"*"<<tmp%10<<endl;
f=false;
break;
}
vis1[tmp%10]=1; //对回溯产生了后效性
tmp/=10;
}
if(f) print(sum);
}
return ;
}
for(int i=0;i<=9;i++){
if(!vis[i]){
vis[i]=1;
dfs(sum*10+i,cnt+1);
vis[i]=0;
}
}
}
int main() {
while(cin>>n && n){
if(k++) cout<<endl;
flag=false;
memset(vis,0,sizeof(vis));
dfs(0,0);
if(!flag) cout<<"There are no solutions for "<<n<<'.'<<endl;
}
return 0;
}