Uva725 Division

题意:

每组测试数据输入一个值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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值