two+two=four的解(全排列与深搜)

题目含义

t w o ,f u r分别是0,1,2,3,4,5,6,7,8,9里面的六个数字。我们要找到它们组合使得two+two=four的等式成立,即
   ~~    two
+ two
----------
  ~   four

解题思路

全排列枚举

1.for循环嵌套有点麻烦,我们直接使用c++自带的全排列函数来完成(next_permutation)
2.我们使用map来保证不会有重复的组合,因为10个数字我们只使用了前6个,所以全排列会有重复项
3.通过f=0,t=0 continue适当提速

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int num[10];
int ans=0;
map<int,int> m;
int main(){
	for(int i=0;i<10;i++) num[i]=i;
	do{
		if(num[5]==0||num[0]==0) continue;
		int t=num[0];
		int w=num[1];
		int o=num[2];
		int r=num[3];
		int u=num[4];
		int f=num[5];
		int two=t*100+w*10+o;
		int four=f*1000+o*100+u*10+r;
		if(two*2==four&&!m.count(two)){
			cout<<" "<<t<<w<<o<<endl;
			cout<<"+"<<t<<w<<o<<endl;
			cout<<f<<o<<u<<r<<endl;
			cout<<"*****************"<<endl;
			ans++;
			m[two]=1;
		}
	}while(next_permutation(num,num+10));
	cout<<"一共有"<<ans<<"种解答"<<endl; 
	return 0;
} 
// two
// two
//four
// owtruf

深搜

深搜递归函数参数解释:
vector a;//用来存放组合的数字
map m; //用存放哪些数字已经用过了,这样确保了数字的唯一性
cnt; //记录了当前a的深度,也可以没有这个参数,用a.size()来代替

注意点:
1.递归的a,m,cnt是需要回溯的,cnt是用的传参+1,所以不用特意再减一,因为cnt+1没有改变cnt的值
2.剪枝的说明
一. f=1,说明t一定要大于5
二. 结果一定满足oo=r||r+10
三. 结果一定满足w
w+(o*o)%10=u||u+10

#include<iostream>
#include<vector>
#include<map>
using namespace std;
int ans=0;//最终的解法 
void check(vector<int> num){
	//f一定是1的  f=1 
	int t=num[0];
	int o=num[1];
	int r=num[2];
	int w=num[3];
	int u=num[4];
	int two=t*100+w*10+o;
	int four=1000+o*100+u*10+r;
	if(two*2==four){
		cout<<" "<<t<<w<<o<<endl;
		cout<<"+"<<t<<w<<o<<endl;
		cout<<1<<o<<u<<r<<endl;
		cout<<"*****************"<<endl;
		ans++;		
	}	
}
void dfs(vector<int> a,map<int,int> m,int cnt){
	if(cnt==5) {
		check(a);return ;
	}
	//深搜剪枝1 大于5才能进1
	if(cnt==1&&a[0]<6) return ;
	//深搜剪枝2 个位数不满足要求
	if(cnt==3&&a[1]*2!=a[2]&&a[1]*2!=10+a[2]) return;
	//深搜剪枝3 十位数不满足要求 
	if(cnt==5&&a[3]*2+(a[1]*2)%10!=a[4]&&a[3]*2+(a[1]*2)%10!=10+a[4]) return ;
	for(int i=0;i<10;i++){
		if(i==1) continue;//f是1 
		if(!m.count(i)){
			a.push_back(i);
			m[i]=1;
			dfs(a,m,cnt+1);
			//回溯 
			a.pop_back();
			m.erase(m.find(i));
		}
	}  
}
int main(){
	vector<int> a;
	map<int,int> m;
	int cnt=0;
	dfs(a,m,cnt);
	cout<<"一共有"<<ans<<"种解答"<<endl; 
	return 0;
}

结果展示

在这里插入图片描述

其中深搜运行0.009s

其中全排运行0.137s

如何测试运行时间

 //计算一段程序运行的时间
 #include<iostream>
 #include<ctime>
 using namespace std;
 int main()
 {
     clock_t startTime,endTime;
     startTime = clock();//计时开始
     for (int i = 0; i < 2147483640; i++)
     {
         i++;
     }
     endTime = clock();//计时结束
     cout << "The run time is: " <<(double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值