0
点赞
收藏
分享

微信扫一扫

POJ1029寻找假币(枚举法/蛮力法)

False coin

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 27763Accepted: 7858

Description

The "Gold Bar"bank received information from reliable sources that in their last group of N coins exactly one coin is false and differs in weight from other coins (while all other coins are equal in weight). After the economic crisis they have only a simple balance available (like one in the picture). Using this balance, one is able to determine if the weight of objects in the left pan is less than, greater than, or equal to the weight of objects in the right pan.
In order to detect the false coin the bank employees numbered all coins by the integers from 1 to N, thus assigning each coin a unique integer identifier. After that they began to weight various groups of coins by placing equal numbers of coins in the left pan and in the right pan. The identifiers of coins and the results of the weightings were carefully recorded.
You are to write a program that will help the bank employees to determine the identifier of the false coin using the results of these weightings.

Input

The first line of the input file contains two integers N and K, separated by spaces, where N is the number of coins (2<=N<=1000 ) and K is the number of weightings fulfilled (1<=K<=100). The following 2K lines describe all weightings. Two consecutive lines describe each weighting. The first of them starts with a number Pi (1<=Pi<=N/2), representing the number of coins placed in the left and in the right pans, followed by Pi identifiers of coins placed in the left pan and Pi identifiers of coins placed in the right pan. All numbers are separated by spaces. The second line contains one of the following characters: '<', '>', or '='. It represents the result of the weighting:
'<' means that the weight of coins in the left pan is less than the weight of coins in the right pan,
'>' means that the weight of coins in the left pan is greater than the weight of coins in the right pan,
'=' means that the weight of coins in the left pan is equal to the weight of coins in the right pan.

Output

Write to the output file the identifier of the false coin or 0, if it cannot be found by the results of the given weightings.

Sample Input

<span style="color:#000000">5 3
2 1 2 3 4
<
1 1 4
=
1 2 5
=</span>

Sample Output

<span style="color:#000000">3</span>

Source

Northeastern Europe 1998

方法与小结:

  1. 巧用bool型函数,嵌套使用,利用反证思维。即假设正确与实际结果出现矛盾则结果在假设的反方。
  2. 本题采用穷举法求解,例出了所有可能结果,遍历求解了所有情况。代码量比较多,但思路清晰便于理解,比较适合初学者解题。

代码:

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 1000
#define Maxx 100
using namespace std;

struct Node {//记录一次称量的状态和结果
    int num;//天平左右两端各有多少枚硬币
    int left[Max/2];//左盘硬币的编码数组
    int right[Max/2];//右盘硬币的编码数组
    char result;//< > = 三种结果
}node[Maxx];

//函数判断一次假设与结果是否矛盾
//state创建一个假设对象
//bool weight表示假设假币比真币重还是轻 true表示重 false表示轻
//falaseCoin 表示假币
bool JugeOnce(int falseCoin, struct Node state, bool weight)
{
    switch (state.result)//假币有且只有一枚
    {
    case'<'://比较结果左轻右重
        if (weight)//重 符合< 则假币在右盘
        {
            for (int i = 0; i <= state.num; i++)//遍历天平右边的硬币
            {
                if (state.right[i] == falseCoin)
                {
                    return true;//假设没矛盾
                }
            }
            return false;//假设与称量结果存在矛盾
        }
        else//假设假币轻 假币在左边
        {
            for (int i = 0; i <= state.num; i++)//遍历天平左边的硬币
            {
                if (state.left[i] == falseCoin)
                {
                    return true;//假设没矛盾
                }
            }
            return false;//假设与称量结果存在矛盾
        }
        break;
    case'>'://比较结果左重右轻
        if (weight)//假币重 符合> 则假币在左盘
        {
            for (int i = 0; i <= state.num; i++)//遍历天平左边的硬币
            {
                if (state.left[i] == falseCoin)//天平左边某硬币就是我们所找的假币
                {
                    return true;//假设与称量结果没有矛盾
                }
            }
            return false;//假设与称量结果存在矛盾
        }
        else
        {
            for (int i = 0; i <= state.num; i++)//遍历天平右边的硬币
            {
                if (state.right[i] == falseCoin)//天平右边某硬币就是我们所找的假币
                {
                    return true;//假设与称量结果没有矛盾
                }
            }
            return false;//假设与称量结果存在矛盾
        }
        break;
    default://左右两边相等,假币没有出现在天平中
        for (int i = 0; i <= state.num; i++)//遍历天平右边的硬币
        {
            if (state.right[i] == falseCoin)//天平右边某硬币就是我们所找的假币
            {
                return false;//假设与称量结果存在矛盾
            }
        }
        for (int i = 0; i <= state.num; i++)//遍历天平左边的硬币
        {
            if (state.left[i] == falseCoin)//天平左边某硬币就是我们所找的假币
            {
                return false;//假设与称量结果存在矛盾
            }
        }
        return true;//假设与称量结果没有矛盾
        break;
    }
}

int main()
{
    int n, m, ans=0;//硬币个数 天平测量数,结果
    scanf_s("%d%d", &n, &m);
    int pivote = 1; //从node[1]开始记录称重次数 
    while (n > 0 && m > 0)
    {
        for (int i = 1; i <= m; i++)//循环输入m次,枚举每一个的个数
        {
            scanf_s("%d", &node[pivote].num);//输入左右盘的币
            for (int j = 1; j <= node[pivote].num; j++)
                scanf_s("%d", &node[pivote].left[j]);//左盘编号
            for (int j = 1; j <= node[pivote].num; j++)
                scanf_s("%d", &node[pivote].right[j]);//右盘编号
            getchar();
            node[pivote++].result = getchar();
        }
        int falsecount = 0;//假币计数
        for (int i = 1; i <= n; i++) //枚举判断有问题的硬币个数
        {
            bool flag = true;//flag表示硬币i是假币
            for (int j = 1; j < pivote; j++)//测试为重的情况
            {
                if (!JugeOnce(i, node[j], false))
                {
                    flag = false;
                    break;
                }
            }
            if (flag) 
            {
                falsecount++;
                if (falsecount > 1)//若个数大于1,则说明无法判断
                {
                    printf("0\n");
                    return 0;
                }
                ans = i;
            }
            else// 若不满足重情况,则测试为轻的情况
            {
                flag = true;
                for (int j = 1; j < pivote; j++) //测试为轻的情况
                {
                    if (!JugeOnce(i, node[j], true))
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag)
                {
                    falsecount++;
                    if (falsecount > 1)//若个数大于1,则说明无法判断
                    {
                        printf("0\n");
                        return 0;
                    }
                    ans = i;
                }
            }

        }
        printf("%d\n", ans);//输出结果
        return 0;
    }
}

举报

相关推荐

0 条评论