算法起步(3)抽签问题—合二为一(上)

来源:互联网 发布:apache用户访问认证 编辑:程序博客网 时间:2024/04/29 07:50

抽签问题(C++)—合二为一(上)
你的朋友提议玩一个游戏:把写有数字的n个纸片放入一个袋子里,
你可以从中抽取4张纸片,每次抽取后把纸片放回到袋子里,如果
抽取的4张纸片上的数字和为m,就算你赢,否则你输,抽了很多
次,结果你完败,那么我可以胜利吗?假设纸牌上的数字依次为k1,
k2,k3,k4,….ki,试写一个程序判断你是否有胜利的可能
限制条件:
n(1,50)
m(1,10^8)
ki(1,10^8)

const int MAX_N = 50;int main(){    //是否查找到符合条件的组合的标志    bool f=false;    int n,m;    int k[MAX_N];    //从标准输入输入    scanf("%d %d",&n,&m);    for(i = 0;i<n;i++){    scanf("%d",&k[i]);}    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(m==k[a]+k[b]+k[c]+k[d])    f=true;}}}}    //从标准输出输出    if(f)    //printf("%d/n",yes);    puts("Yes");    else{    //printf("%d/n",no);    puts("no");}}

是否觉得超级简单,那么问题来了,当n = 1000时,我们的算法复杂度1000^3,我们需要降低其复杂度

如何去做,如何结合二分法降低其复杂度
二分法:将数据从小到大排列,取中间数,如果比中间数大,在后半部分查找,如果比中间数小,在前半部分查找

    int n,m;    int k[MAX_N];    bool f = false;    bool binary_search(int x)    //k[l],k[l+1],k[l+2]....k[r-1]    {    while(r-1>1){    int l=0;    int r=n;    int i=(l+r)/2;    if(x>k[i])    l=i+1;    else if(x==k[i])    return true;    else    r=i;    }    return false;    }    void solve(){    sort(k,k+n);    for(a = 0;a<n;a++){    for(b = 0;b<n;b++){    for(c = 0;c<n;c++){    if(binary_search(m-k[a]-k[b]-k[c])){    f = true;}}}}    if(f)    puts("Yes");    else    puts("no");}
第一次优化算法后,让我们来看看复杂度排序nlogn循环n^3lognn^3logn比nlogn大,所以复杂度为n^3logn
0 0
原创粉丝点击