(1.1)抽签

题目

(1.1)抽签_第1张图片
(1.1)抽签_第2张图片
(1.1)抽签_第3张图片

代码

方案1 O(n4)

#include

const int MAX_N = 50;

int main(){
	int n, m, k[MAX_N];
	
	// 从标准输入 
	scanf("%d %d", &n, &m);
	for(int i = 0 ; i < n ; i ++){
		scanf("%d", &k[i]);
	}
	
	//是否找到和为m的组合的标记 
	bool f = false;
	
	//枚举所有的方案
	for(int a = 0 ; a < n ; a ++){
		for(int b = 0 ; b < n ; b ++){
			for(int c = 0 ; c < n ; c ++){
				for(int d = 0 ; d < n ; d ++){
					if(k[a] + k[b] + k[c] + k[d] == m){
						f = true;
					}
				}
			}
		}
	}
	
	//输出到标准输出
	if(f) puts("Yes");
	else puts("No");
	
	return 0;
} 

方案2(排序:O(nlogn) 循环O(n3logn) )

将方案1中循环体内部的检查是否有使得 ka + kb + kc + kd == m 进行移项,得到了另一个表达式 检查是否有d使得使得 kd == m - ka - kb - kc

检查数组k中的所有的元素,判断是否有m - ka - kb - kc
(此处使用了 二分搜索O(logn)的方法,C++的STL库中有类似的函数)

#include
#include
#include
using namespace std;

const int MAX_N = 50;
int n, m, k[MAX_N];

bool binary_search(int x){
	// x存在的范围是k[l],k[l+1],...,k[r-1] 
	int l = 0, r = n;
	
	while(r - l >= 1){
		int i = (r + l) / 2;
		if(k[i] == x)
			return true; // 找到x
		else if(k[i] < x)
			l = i + 1;
		else
			r = i; 
	}
	
	//没找到x
	return false; 
}

void solve(){
	
	// 二分查找之前先排序
	sort(k, k + n);
	bool f = false;
	
	for(int a = 0 ; a < n ; a ++){
		for(int b = 0 ; b < n ; b ++){
			for(int c = 0 ; c < n ; c ++){
				//将最内测的循环替换成二分查找 
				if(binary_search(m - k[a] - k[b] - k[c])){
					f = true;
				} 	
			}
		}
	}
	
	if(f){
		puts("Yes");
	}else{
		puts("No");
	}	 
}

int main(){
	
	// 从标准输入 
	scanf("%d %d", &n, &m);
	for(int i = 0 ; i < n ; i ++){
		scanf("%d", &k[i]);
	}
	
	solve();
	return 0;
} 

方案3(排序:O(n2logn) 循环O(n2logn) )

检查是否有c和d使得 kc + kd == m - ka - kb

此时,并不能直接使用二分搜索的方法,如果预先枚举 kc + kd 所得的n2个数字并排好序,就可以使用二分搜索了。

#include
#include
#include
using namespace std;

const int MAX_N = 50;
//输入 
int n, m, k[MAX_N];

//保存2个数的和的数列
int kk[MAX_N * MAX_N]; 

bool binary_search(int x){
	// x存在的范围是kk[l],kk[l+1],...,kk[r-1] 
	int l = 0, r = n*n;
	
	// 反复操作直到存在范围为空 
	while(r - l >= 1){
		int i = (r + l) / 2;
		if(kk[i] == x)
			return true; // 找到x
		else if(kk[i] < x)
			l = i + 1;
		else
			r = i; 
	}
	
	//没找到x
	return false; 
}

void solve(){
	// 枚举k[c]+k[d]的和
	// 其实,存储 n(n+1)/2  个数字就够了 
	for(int c = 0 ; c < n ; c ++){
		for(int d = 0 ; d < n ; d ++){
			kk[c*n+d] = k[c] + k[d];
		}
	} 
	// 排序以进行二分搜索 
	sort(kk, kk + n*n);
	bool f = false;
	
	for(int a = 0 ; a < n ; a ++){
		for(int b = 0 ; b < n ; b ++){
			for(int c = 0 ; c < n ; c ++){
				//将最内测的循环替换成二分查找 
				if(binary_search(m - k[a] - k[b])){
					f = true;
				} 	
			}
		}
	}
	
	if(f){
		puts("Yes");
	}else{
		puts("No");
	}	 
}

int main(){
	
	// 从标准输入 
	scanf("%d %d", &n, &m);
	for(int i = 0 ; i < n ; i ++){
		scanf("%d", &k[i]);
	}
	
	solve();
	return 0;
} 

你可能感兴趣的:(算法)