读书笔记<程序设计>|抽签

抽签

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

限制条件:

1<=n<=50

1<=m<=10^8

1<=ki<=10^8

一般思路:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int main(int argc, char *argv[])
{
  int m,n,i,j,k,l,a[50];
  bool flag=false;//标志是否存在
  scanf("%d",&n);
  scanf("%d",&m);
  for(i=0;i<n;i++){
                   scanf("%d",&a[i]);
  }
  for(i=0;i<n;i++){
      for(j=0;j<n;j++){
         for(k=0;k<n;k++){
            for(l=0;l<n;l++){
               if(a[i]+a[j]+a[k]+a[l]==m){
                   flag=true;
               }
            }
         }
      }
  }
  if(flag)printf("%s\n","Yes");
  else printf("%s\n","No");
  system("PAUSE");    
  return 0;
}

注意要点:

对于bool类型的未定义解决办法参考:http://cprogrammer.blog.163.com/blog/static/18340047620113993850877/

原因:http://blog.csdn.net/xiaohaijiejie/article/details/43973237

个人体会

1.由于bool不是c的关键字,需要另外自申明typedef enum __bool{false,true}bool;或者利用其他的函数库#include<stdbool.h>

2.时间复杂度为o(n^4)

3.考虑复杂度是否可以变为o(n^3logn)、o(n^2logn)等。

 延伸1:利用二分法实现n^3logn的时间复杂度。

思路:先利用对数组进行排序,然后对四个数中的m-a[i]-a[j]-a[k]进行二分法查找。排序需要nlogn,二分查找需要n^3logn,所以需要n^3logn。

首先需要明确的是我们利用的是c库中现有的函数sort():此函数有两种用法:

(1)sort(RandomIt first,RandomIt last):其中变量的类型可以是人意的类型,int,char,list,vector……。

(2)sort(RandmIt first,RandomIt last,Compera comp):其中comp是可以自定义的比较函数。

顺便提一下qsort函数,使不同于sort函数的,从另一个角度来讲,sort函数包括qsort()函数,sort函数包含qsort函数、堆排序、插入排序。

基本代码如下(其中由于编译器的问题我分别用vs2013和devc++v4.9.9.2版本比较老,其中代码中的细节需要依据具体的编译器进行改动):

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <algorithm>
#include <iostream>
int a[1000000];//很多数,这样sort函数的性能才能体现出来。
int m, n;//方便binaray_find函数的利用 
bool binaray_find(int x){
    int i = 0, j = n;
    for (i = (i + j) / 2; i +1<= j;){
        if (a[i] == x)return true;
        else if (x>a[i]){
            i = (i + j) / 2+1;
        }
        else{
            j = (i + j) / 2;
        }
    }
    return false;
}
int main(int argc, char *argv[])
{
    int i, j, k;
    bool flag = false;
    scanf_s("%d%d",&n,&m);
    for (i = 0; i < n; i++){
        scanf_s("%d",&a[i]);
    }
    std::sort(a, a + n);
    for (i = 0; i < n; i++){
        printf("%d",a[i]);
    }
    for (i = 0; i<n; i++){
        for (j = 0; j<n; j++){
            for (k = 0; k<n; k++){
                if (binaray_find(m - a[i] - a[j] - a[k]))flag = true;
            }
        }
    }
    if (flag)printf("%s", "Yes");
    else printf("%s", "No");
    system("PAUSE");
    return 0;
}

主要是由于c中没有现成的sort函数,所以代码中含有了c++的成分。

个人体会:整体的思路还是比较简单的,但是对于细节的实现binaray_find()函数的实现还需要细细琢磨。

延伸2:利用二分法实现o(n^2logn)

同样的思路,只是把kc+kd=m-ka-kb;预先枚举出kc+kd的所有的n^2个数字并排好序,以便利用二分法搜索了。

#include <cstdlib>
#include <iostream>
#include <algorithm>
#define Num 10000
using namespace std;
int m, n, aa[Num*(Num + 1) / 2], a[Num];
bool binaray_find(int x){
    int l = 0, r = n*(n + 1) / 2;
    while (r - l >= 1){
        int i = (r + l) / 2;
        if (aa[i] == x)return true;
        else if (aa[i]<x)l = i + 1;
        else r = i;
    }
    return false;
}
int main(int argc, char *argv[])
{
    int i, j;
    cin >> n >> m;
    bool flag = false;
    for (i = 0; i<n; i++){
        cin >> a[m];
    }
    for (i = 0; i<n; i++){
        for (j = i; j<n; j++){
            aa[j + i*(n - i)] = a[i] + a[j];
        }
    }
    sort(aa, aa + n*(n + 1) / 2);
    for (i = 0; i<n; i++){
        for (j = 0; j<n; j++){
            if (binaray_find(m - a[i] - a[j]))flag = true;
        }
    }
    if (flag)cout << "Yes" << endl;
    else cout << "No" << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}

今天先这样,代码确实有问题

posted @ 2016-08-15 22:29  Zero90  阅读(150)  评论(0编辑  收藏  举报