抽签

试题描述

你的朋友提议玩一个游戏:将写有数字的n 个纸片放入口袋中,你可以从口袋中抽取4 次纸片,每次记下纸片上的数字后都将其放回口袋中。如果这4 个数字的和是m,就是你赢,否则就是你的朋友赢。你挑战了好几回,结果一次也没赢过,于是怒而撕破口袋,取出所有纸片,检查自己是否真的有赢的可能性。请你编写一个程序,判断当纸片上所写的数字是k1,k2, …, kn 时,是否存在抽取4 次和为m 的方案。

输入
第一行为两个整数n,m;第二行为n个整数k1,k2, …, kn 。
输出
如果存在,输出“Yes”;否则,输出“No”。
输入示例
3 10
1 3 5
输出示例
Yes
其他说明
1 ≤ n ≤ 50
1 ≤ m ≤ 10^8
1 ≤ ki ≤ 10^8

这道题最简单的做法就是:四个循环。但是这种情况下的时间复杂度太高了,所以需要优化。我用的是三个循环里面套二分,这样速度会由O(n^4)变为O(n^3logn),快了许多。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 int a[100];
 5 int x,n,m;
 6 bool solve(int mid)   //二分查找 
 7 {
 8     int L=1,R=n;
 9     
10     while(R-L>=1)
11     {
12         mid=(L+R)/2;
13         if(a[mid]==x) return true;
14         else if(a[mid]<x) L=mid+1;
15         else R=mid;
16     }
17     return false;
18 }
19 
20 int main()
21 { 
22     bool hh=false;
23     scanf("%d%d",&n,&m);
24     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
25     sort(a+1,a+n);
26     for(int i=1;i<=n;i++)  //三重循环 
27     {
28         for(int j=1;j<=n;j++)
29         {
30             for(int k=1;k<=n;k++)
31             {
32                 x=m-a[i]-a[j]-a[k];
33                 if(solve(x)) {printf("Yes");hh=true;break;}
34             }
35             if(hh==true) break;
36         }
37         if(hh==true) break;
38     }
39     if(hh==false) printf("No");
40     //system("pause");
41     return 0;
42 }
抽签

 

posted @ 2015-11-21 10:55  姚呵呵  阅读(314)  评论(0编辑  收藏  举报