poj1029 False coin

来源:互联网 发布:后期软件培训 编辑:程序博客网 时间:2024/06/06 00:33

链接:http://poj.org/problem?id=1029

有个类似的题是在之前学枚举的时候遇到过,之前的那个例子要简单些。但原理是一样的。所以拿来这个题借鉴一下。

对于假币,存在两种情况:比真币重,或者,比真币轻。又总共有n个硬币,所以有2*n那种情况。

对于每一个硬币,要满足题中m个比对结果,则这个硬币为假硬币。

咳咳。。。当然对于一般的数据,上面的方法是正确的。但对于某些特殊的数据还是要进行判断。

这里,我给两组数据:

5 2
1 1 4
=
1 2 5
=

answer:3

 

6 2
1 1 4
=
1 2 5
=

answer:0
在第一个例子中,我们可以发现,硬币3是满足所有的比对结果的,所以3是假硬币。

而对于第二个例子,我们又可以发现,硬币3和6均满足所有的比对结果。而这时,结果就有可能不对,所以我在这里设置了temp变量,来排除这种情况。

还有一个例子:

2 1

1 1 2

>

answer:0

这个代码刚写好的时候有很多bug,所以修修补补之后,在最后的判断条件上有点乱。主要就是用flag变量来记录不同的情况来进行判断。

#include<stdio.h>#include<string.h>int left[105][505],right[105][505];//left[i][j]用于存储左边天平的硬币//right[i][j]用于存储右边天平的硬币char res[105][1];//res[i][j]用来存储每次比对的结果,即“>”、“<”、“=”int n,k,p;int find(int *seq,int x)//查找x是否存在数列seq中{   int i;   for(i=0;i<505;i++)   if(seq[i]==x)   return 1;return 0;}int IsLight(int x)//如果假币比真币轻{int i;for(i=0;i<k;i++)switch(res[i][0]){       case '<':if(!find(right[i],x))//对于“>”,则假币必定存在于右盘              return 0;   break;       case '>':if(!find(left[i],x))//对于“<”,则假币必定存在于左盘               return 0;   break;       case '=':if(find(left[i],x)||find(right[i],x))//对于“=”,则假币不存在任何一个盘                return 0;   break;}return 1;}int IsHeavy(int x)//如果假币比真币重,同上{int i;for(i=0;i<k;i++)switch(res[i][0]){       case '<':if(!find(left[i],x))              return 0;   break;       case '>':if(!find(right[i],x))               return 0;   break;       case '=':if(find(left[i],x)||find(right[i],x))                return 0;   break;}return 1;}int main(){int i,j;int pos1,pos2,flag1,flag2,ans,temp;while(scanf("%d%d",&n,&k)!=EOF){flag1=0;flag2=0;ans=0;pos1=0;pos2=0;temp=0;memset(left,0,sizeof(left));memset(right,0,sizeof(right));  for(i=0;i<k;i++)  {     scanf("%d",&p); for(j=0;j<p;j++) scanf("%d",&left[i][j]); for(j=0;j<p;j++) scanf("%d",&right[i][j]); getchar(); scanf("%c",&res[i][0]);   }  for(i=1;i<=n;i++)//枚举每一个硬币               //此题中假币只有一个,所以结果唯一  {    if(IsLight(i)){            pos1=i;flag1++;}if(IsHeavy(i)){pos2=i;flag2++;}         if((flag1==flag2)&&flag1&&flag2&&pos1==pos2&&pos1!=temp) {ans++;temp=pos1; }  }if((flag1==1)&&!flag2)//一般的数据,只有一个比真币轻的假硬币,满足所有比对结果   printf("%d\n",pos1);if(!flag1&&(flag2==1))//一般的数据,只有一个比真币重的假硬币,满足所有比对结果   printf("%d\n",pos2);if((flag1==flag2)&&flag1&&flag2)//比对的所有结果是“等号”{if(pos1==pos2&&ans==1)//同一个硬币,且只有一个,即ans==1(针对以上两个例子)   printf("%d\n",pos1);elseprintf("%d\n",0);//否则为0,如第二个例子和第三个例子}    if((!flag1&&!flag2)||((flag1>1||flag2>1)&&(flag1!=flag2)))//flag1=0&&flag2=0,没有一个满足所有比对结果的硬币//flag1>1||flag2>1且flag1!=flag2,有多个满足所有结果的硬币,即结果不唯一,不满足题意printf("%d\n",0);}  return 0;}


 

0 0