TZOJ 1083: False coin
思路和1080: Counterfeit Dollar差不多,第一次看到这题就想到用枚举的方法枚举每一枚硬币去跑一遍记录,最后一定要注意一些细节。
首先假设硬币i为假币,并且当它为轻的硬币;则:
1、当记录为左边<右边时,因为它是轻的硬币,所以在左边去寻找这枚硬币,如果找到了那么跑下一条记录,否则枚举下一枚硬币。
2、当记录为左边>右边,同理得在右边寻找硬币…
3、当记录为左边=右边时,寻找左边和右边是否存在这枚硬币,如果存在则枚举下一枚硬币。
当其中一枚跑完所有记录时,用res[i]++记录第i枚硬币满足多少次。
同理当假币为重的情况和上面一样。
最后跑一边res[]数组,寻找是否只有一枚硬币满足条件输出这枚硬币,否则有超过1枚硬币满足记录或者都不满足记录则输出0;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
//#define ll long long int
using namespace std;
int N,K;
int l[100][100];
int r[100][100];
int num[1000];
int res[1000];
char f[1000];
int cnt=0;
void istrue(int x,int t){ //t为1表示这枚硬币是重的,为0表示轻的
int flag;
for(int i=0;i<K;i++){ //遍历每个记录
flag=0; //每次跑一条记录都要重新标记
int *ll=l[i]; //获取左边的信息
int *rr=r[i]; //获取右边的信息
if(f[i]=='<'){
if(t){ //遍历该硬币是否满足条件
for(int j=0;j<num[i];j++){
if(rr[j]==x){
flag=1;
}
}
if(flag==0)return;
}else{
for(int j=0;j<num[i];j++){
if(ll[j]==x){
flag=1;
}
}
if(flag==0)return;
}
}
if(f[i]=='>'){
if(t){
for(int j=0;j<num[i];j++){
if(ll[j]==x){
flag=1;
}
}
if(flag==0)return;
}else{
for(int j=0;j<num[i];j++){
if(rr[j]==x){
flag=1;
}
}
if(flag==0)return;
}
}
if(f[i]=='='){
for(int j=0;j<num[i];j++){
if(ll[j]==x){
return;
}
}
for(int j=0;j<num[i];j++){
if(rr[j]==x){
return;
}
}
flag=1;
}
}
if(flag){ //跑完K条记录如果满足条件,将该硬币放入数组
res[x]++;
return;
}
}
int main(int argc, char const *argv[])
{
memset(res,0,sizeof(res));
scanf("%d %d",&N,&K);
int count;
for(int i=0;i<K;i++){
scanf("%d",&count);
num[i]=count;
for(int j=0;j<count;j++)scanf("%d",&l[i][j]);
for(int k=0;k<count;k++)scanf("%d",&r[i][k]);
getchar();
scanf("%c",&f[i]);
}
for(int i=1;i<=N;i++){
istrue(i,1); //枚举每个硬币是轻
istrue(i,0); //不知道硬币是轻还是重所有都要枚举
}
int kk=0;
for(int i=1;i<=100;i++){ //寻找满足条件的硬币个数
if(res[i]!=0){
cnt++;
kk=i;
}
}
if(N==2){ //当然2枚硬币一定输出0
printf("0\n");
}else if(cnt==1)printf("%d\n",kk);
else printf("0\n");
return 0;
}
这题解法不唯一我这方法肯定不是最好的