Visitors hit counter dreamweaver

枚举--称硬币

问题描述
  赛利有 12 枚银币。其中有11 枚真币和1 枚假币。假币看起来和真币没有区别,但是重
量不同。但赛利不知道假币比真币轻还是重。于是他向朋友借了一架天平。朋友希望赛利称
三次就能找出假币并且确定假币是轻是重。例如:如果赛利用天平称两枚硬币,发现天平平
衡,说明两枚都是真的。如果赛利用一枚真币与另一枚银币比较,发现它比真币轻或重,说
明它是假币。经过精心安排每次的称量,赛利保证在称三次后确定假币。

输入数据
输入有三行,每行表示一次称量的结果。赛利事先将银币标号为A-L。每次称量的结果
用三个以空格隔开的字符串表示:天平左边放置的硬币 天平右边放置的硬币 平衡状态。其
中平衡状态用"up'', "down'', 或 "even''表示, 分别为右端高、右端低和平衡。天平左右的硬币
数总是相等的。


输出要求:
输出哪一个标号的银币是假币,并说明它比真币轻还是重。


输入样例
1
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
输出样例
K is the counterfeit coin and it is light.

我的思路:

  我采用的是比较笨的方法,就是先根据给出的条件,通过设置标准位,来找出假币,然后再判断假币是比硬币轻还是比硬币重。思路不难想,就是实现有点多。所以造成我的代码很长。当然这还不符合OJ上面的输入和输出,我就不想改了,将就着吧。

//先把假币找出来,然后再判断是重还是轻

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

#define BASE 65

int Jude(char c,const char *szLeft, const char *szRight,const char *szStr)
{//返回1表示比真币轻,返回2表示比真币重
    int i=0;

    while (szLeft[i])
    {
        if (c == szLeft[i])  //假币在左边
        {
            if (strcmp(szStr,"up") == 0)
            {
                return 2;
            }
            else
            {
                return 1;
            }
        }
        i++;
    }
    
    //在右边
    if(strcmp(szStr,"up") ==0)
    {
        return 1;
    }
    else
    {
        return 2;
    }
}

int main()
{
    char left[7],right[7],str[5];
    char tmp_l[7],tmp_r[7],tmp_str[5];  //用来存储不平衡的那行
    int result[12],i,Count = 3;
    FILE *fp;
    memset(result,0,sizeof(result));
    fp = fopen("in.txt","r");
    if (fp == NULL)
    {
        printf("Fopen failed.\n");
        return -1;
    }
while (Count)
{
    memset(left,0,sizeof(left));
    memset(right,0,sizeof(left));

    fscanf(fp,"%s%s%s",left,right,str);
    //printf("left:%s,right:%s,str:%s\n",left,right,str);
    if (strcmp(str,"even") == 0)
    {  
        i=0;
        while (left[i])
        {
            result[left[i]-BASE] = 1;   //等于1表示是真币
            i++;
        }

        i=0;
        while (right[i])
        {
            result[right[i]-BASE] = 1;   
            i++;
        }
    }

    if (strcmp(str,"up") == 0)
    {
        strcpy(tmp_l,left);
        strcpy(tmp_r,right);
        strcpy(tmp_str,str);

        i=0;
        while (left[i])
        {
            if (result[left[i] - BASE] == 0)
            {
                result[left[i]-BASE] = 2;     //表示有可能是假币
            }
            i++;
        }
        
        i=0;
        while(right[i])
        {
            if (result[right[i] - BASE] == 0)  //没称过
            {
                result[right[i] - BASE] = 2;
            }
            i++;
        }
    }

    if (strcmp(str,"down") == 0)
    {
        strcpy(tmp_l,left);
        strcpy(tmp_r,right);
        strcpy(tmp_str,str);

        i=0;
        while (right[i])
        {   
            if (result[right[i] - BASE] == 0)  //没称过
            {
                result[right[i]-BASE] = 2;
            }
            i++;
        }

        i=0;
        while(left[i])
        {
            if (result[left[i] - BASE] == 0)  //没称过
            {
                result[left[i] - BASE] = 2;
            }
            i++;
        }
    }

    Count --;

}

    for(i=0; i < 12; i++)
    {
        if (result[i] == 2)
        {
            if(Jude(BASE + i,tmp_l,tmp_r,tmp_str) == 1)
            {
                printf("%c is the counterfeit coin and it is light.\n",BASE + i);
            }
            else
            {
                printf("%c is the counterfeit coin and it is heavy.\n",BASE + i);
            }
        }
    }

    return 0;
}

 

更秒的解法:

  标准答案上的解法是用枚举法,解题思路是跟我的逆过来的。总共12个字母,只有两种情况,比真币轻还是比真币重。那么我们可以去枚举每个硬币的两种情况,总共24种情况。然后用每种情况套入到给出的条件去判断是否都符合,都符合条件了就是我们要的结果。

 

所以说,我们应该学会从不通的角度去考虑问题,有时候逆过来解决问题,可能方法更简单些。

posted @ 2013-04-13 14:13  Jason Damon  阅读(921)  评论(0编辑  收藏  举报