11111 不知道对不对啊,因为没有测试数据,有问题请指出来。
不知道对不对啊,因为没有测试数据,有问题请指出来。
1.dfs思路:
- 将硬币分3堆,如果有余数(0~2),那就一共4堆
- 比较3堆重量,找到有问题的一堆。继续1
- 直到只有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