n枚硬币中找到一个残次的(dfs)

11111 不知道对不对啊,因为没有测试数据,有问题请指出来。


不知道对不对啊,因为没有测试数据,有问题请指出来。

1.dfs思路:

  1. 将硬币分3堆,如果有余数(0~2),那就一共4堆
  2. 比较3堆重量,找到有问题的一堆。继续1
  3. 直到只有2枚硬币和1枚硬币的情况,return。
#include<iostream>
#include<math.h>
#include<stdlib.h>
#include<time.h>
using namespace std;

const int N = 100010;
int coins[N];
int n;
const int CoinN = 100;  //硬币数量,改这个下面的的就不要一一修改了,很方便。要几个硬币就输入几就好了
time_t t;

void Init()
{
	srand((unsigned)time(&t));    //通过时间函数随机生成一个种子数,这个种子数用到下面的rand()里面
	//for (int i = 0; i < 10; i++)
		//cout << rand() % 100<<" ";
	int k = rand() % CoinN;
	while (k == 0)
	{
		k = rand() % CoinN;
	}
	coins[k] =0;
}

int weight_sum(int coins[], int left, int right)  //计算[left,right]区间硬币的重量
{
	int sum = 0;
	for (int i = left; i <= right; i++)
		sum += coins[i];
	return sum;
}

int dfs(int coins[], int coinNum, int left, int right)   //定义dfs,找到区间[left,right]里面的假币
{
	//每次将硬币分为三个等分的部分。很显然这是以边界条件进行递归的过程。
	//所以知道当硬币只有3个或者小于三个的时候要return,也就是终止条件.
	//分三种情况,余数为0,1,2;
	int Coin_3 = floor(coinNum / 3);   //将硬币分为三个部分
	int r = coinNum % 3;    //将硬币分为三个部分后的余数部分,可能是0,1,2

	//分情况讨论
	if (coinNum == 1)   //首先说明,因为寻找硬币是一个不停删选的过程,如果前面找到了硬币,就不会走到这一步。如果走到这一步,说明这个
		//硬币一定是假的
		return left;

	if (coinNum == 2)   //同理,假的硬币一定在这两个中间寻找,那么思路就是从这两个硬币之外再随意找一个硬币去作为标准(因为这两个硬币
		//之外的硬币一定是真硬币)我们规定(找后面第一个硬币,如果比较的硬币是顺序数的最后两个硬币,那么找前一个硬币)
	{
		int a = coins[left];
		int b = coins[right];
		//a,b有两种情况
		if (a!=b)  //比较 
		{
			int c = right == CoinN ? coins[left - 1] : coins[right + 1];
			if (a == c)   //b是假的
				return right;
			else         //a是假的
				return left;
		}
	}


	//上面是终止条件,下面是核心dfs判断,对余数分类

	if (r == 0)  //余数为0
	{
		int a = weight_sum(coins, left, left + Coin_3 - 1);
		int b = weight_sum(coins, left + Coin_3, left + Coin_3 * 2 - 1);
		int c = weight_sum(coins, left + 2 * Coin_3, left + 3 * Coin_3 - 1);
		if (a == c)
			return dfs(coins, Coin_3, left + Coin_3, left + Coin_3 * 2 - 1);
		if (a == b)
			return dfs(coins, Coin_3, left + 2 * Coin_3, left + 3 * Coin_3 - 1);
		if (b == c)
			return dfs(coins, Coin_3, left, left + Coin_3-1);
	}
	if (r == 1 || r == 2)  //余数为1或余数为2
	{
		int a = weight_sum(coins, left, left + Coin_3 - 1);
		int b = weight_sum(coins, left + Coin_3, left + Coin_3 * 2 - 1);
		int c = weight_sum(coins, left + 2 * Coin_3, left + 3 * Coin_3 - 1);
		//假的硬币要么在三堆一样的硬币里面,要么在余数那一堆里面
		if (a == b && b == c)   //在余数那一堆
			return dfs(coins, r, left + 3 * Coin_3, right);
		else    //在前面三堆
		{
			if (a == c)
				return dfs(coins, Coin_3, left + Coin_3, left + Coin_3 * 2 - 1);
			if (a == b)
				return dfs(coins, Coin_3, left + 2 * Coin_3, left + 3 * Coin_3 - 1);
			if (b == c)
				return dfs(coins, Coin_3, left, left + Coin_3-1);
		}
	}
}


int main()
{
	//随机生成一个假币
	//0表示的,1表示真的。但是不知道轻重
	for (int i = 1; i <= CoinN; i++)  //初始化100个硬币
		coins[i] = 1;
	/*for (int i = 1; i <= 100; i++)
	{
		coins[i] = 0;
		int k = dfs(coins, 100, 1, 100);
		cout << k << endl;
		for (int j = 1; j <= 100; j++)
		{
			cout << coins[j] << " ";
			if (j % 10 == 0)cout << endl;
		}
		cout << endl;
		coins[i] = 1;
	}*/
	Init();    //生成一个假币
	int ans = 0;
	for (int i=1; i <= CoinN; i++)
	{
		cout << coins[i] << " ";
		if (coins[i] == 0)   //记录假币,等会要验证数据
			ans = i;
		if (i % 10 == 0)
			cout << endl;
	}
	cout << "正确答案:" << ans << endl;
		
	cout << endl;
	cout << "自己的答案:" << dfs(coins, CoinN, 1, CoinN) << endl;

	//判断轻重,找一个标准重量
	int k = ans == CoinN ? CoinN-1 : CoinN;
	if (coins[ans] > coins[k])
		cout << "假币重";
	else
		cout << "假币轻";
	return 0;
}

//1 1 1 * 1 0 1 * 1 1 1 *   1
//1 1 1 1 * 1 0 1 1 * 1 1 1 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值