n枚硬币问题

大致说一下问题,就是在n枚硬币中存在一个假币,但不知道假币比真币中还是轻,你只有一个天秤,要你用最少的比较次数找到假币在哪。

本来的思路是不断二分,如果硬币是偶数枚,那恰好能分成两份,第一次分成的这两份肯定一份重一份轻,并且无法判断假币在哪一份里。

但如果把第一份再二分,如果重量相等的话,假币肯定在第一次二分的第二份里。

重复以上过程,不断递归,肯定能得出结果。

奇数个硬币的话就先去掉一个呗,剩下的就和偶数类似了。

不过百度了一下,发现一个三分然后判断的,本来三分我是一点思路都没有的,就感觉三分那个可厉害。

于是我加上了随机生成硬币之后,就有了如下的代码:

c/c++实现

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


int step = 0;
void solve(int coin[], int n, int p, int q)
{
    step=step+1;
    if (n < 3){
        printf("无法判断\n");
        return;
    }
    if (p == q){
        printf("假币的序号为%d, 假币的重量为%d\n", p+1, coin[p]);
    }
    else if (q - p == 1){
        if (p > 0){
            if (coin[p] == coin[0]) solve(coin, n, p + 1, q);
            else solve(coin, n, p, q - 1);
        }
        else if (q < n - 1){
            if (coin[p] == coin[n - 1]) solve(coin, n, p + 1, q);
            else solve(coin, n, p, q - 1);
        }
    }
    else if (p < q){
        int temp = (q - p + 1) / 3;
        int sum1 = 0, sum2 = 0;
        for(int i = 0; i < temp; i++){
            sum1 += coin[p + i];
            sum2 += coin[q - i];
        }
        if (sum1 == sum2){//在中间
            solve(coin, n, p + temp, q - temp);
        }
        else{//在两边,不在中间
            if (sum1 == coin[p + temp] * temp){//左边的和中间的相等,在右边
                solve(coin, n, q - temp + 1, q);
            }
            else{
                solve(coin, n, p, p + temp - 1);
            }
        }
    }
}
int main()
{
    int n,sj0,sj1,sj2;
    int coins[10000];
    scanf("%d",&n);
    srand((int)time(NULL));
    sj0 = rand()%10;
    for(int i = 0; i < n; i++){
        coins[i] = sj0;
    }
    sj1 = rand()%n;
    while(1){
        sj2 = rand()%10;
        if(sj2!=sj0){
            break;
        }
    }
    coins[sj1] = sj2;
    for(int i = 0; i < n; i++){
        printf("%d ",coins[i]);
    }
    printf("\n");
    solve(coins, n, 0, n-1);
    printf("%d\n",step);
    return 0;

}

那个回答链接在这(16楼):https://bbs.csdn.net/wap/topics/290004423 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值