Uva-340. Master-Mind Hints题解
欢迎访问我的Uva题解目录哦https://blog.csdn.net/richenyunqi/article/details/81149109
题目描述
题意解析
题目给出了一个答案序列和一个猜的序列,要求统计出有两个序列中数字相同且位置相同的数字个数strong以及数字相同但位置不同的数字个数weak。
注意点
在统计数字相同但位置不同的数字个数weak时注意不能和数字相同且位置相同的数字进行比较。例如给定的答案序列为1 3 5 5,给定的猜的序列为1 1 2 3,假设序列数字位置由0开始,猜的序列1号位置上的数字1和答案序列0号位置上的数字1相同,但是猜的序列1号位置上的数字1不能被统计进入weak中,因为答案序列0号位置上的数字1和猜的序列0号位置上的数字1数字相同且位置相同,该数字可以被统计进入strong中,那么猜的序列1号位置上的数字1就不能再和答案序列0号位置上的数字1进行比较。而猜的序列3号位置上的数字3和答案序列1号位置上的数字3数字相同,但答案序列1号位置上的数字3并不能统计入strong中,所以该数字可以统计入weak中。通过上述讨论,可以得知需要先统计strong,再统计weak。
算法设计
由于给定的序列中数字范围为1~9,可以定义两个长度为10的一维数组codeFre和guessFre,数组元素下标代表序列中0~9这十个数字,元素内容表示该数字在序列中出现的次数,codeFre和guessFre分别对答案序列和猜的序列中的数字出现频率进行统计。先统计stron,遍历答案序列和猜的序列,如果对应位置上对应数字相同,假设该数字为n,那么strong递增1,以n为下标,将codeFre和guessFre对应元素分别递减1。再统计weak,遍历codeFre和guessFre两个数组,遍历过程中令weak+=min(guessFre[i],codeFreCopy[i])。最后输出strong和weak即可。
C++代码
#include<bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)//for循环的一种用宏表示的简写方式
void readData(int*sequence,int*frequency,int N){//读入数据并统计序列中每个数字出现的频率
fill(frequency,frequency+10,0);
_for(i,0,N){
scanf("%d",&sequence[i]);
++frequency[sequence[i]];
}
}
int main(){
int N,num=0,code[1005],guess[1005],codeFre[10],guessFre[10],codeFreCopy[10];
scanf("%d",&N);
while(N!=0){//N不为0继续游戏
printf("Game %d:\n",++num);
readData(code,codeFre,N);//读取答案序列
readData(guess,guessFre,N);//读取猜的序列
while(guessFre[0]<N){//猜的序列如果数字全为0的话,那么猜的序列0出现的频率就是N,可以用这一点作为一次游戏是否结束的标志
memcpy(codeFreCopy,codeFre,sizeof(codeFre));//将codeFre数组元素拷贝到codeFreCopy中
int strong=0,weak=0;
_for(i,0,N)//统计两个序列中数字相同且位置相同的数字个数strong
if(code[i]==guess[i]){
++strong;
--codeFreCopy[code[i]];
--guessFre[guess[i]];
}
_for(i,0,10) weak+=min(guessFre[i],codeFreCopy[i]);//统计数字相同但位置不同的数字个数weak
printf(" (%d,%d)\n",strong,weak);//输出,注意每行前要输出4个空格
readData(guess,guessFre,N);//再次读入猜的序列
}
scanf("%d",&N);//读取N
}
return 0;
}