PAT乙级题库 1003 我要通过!

守給你的承諾、 提交于 2020-01-18 14:47:07

                                   1003 我要通过! (20分)

“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。

得到“答案正确”的条件是:

  1. 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
  2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
  3. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。

输入格式:

每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过 100,且不包含空格。

输出格式:

每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出 YES,否则输出 NO

输入样例:

8
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA

输出样例:

YES
YES
YES
YES
NO
NO
NO
NO

 解题思路:

  • 第一条规则规定了输入的字符串中只能含有P、A、T三种字符。
  • 第二条规则需要与第三条规则结合起来看。
  • 第三条规则最有意思,当打上眼看的时候,一脸懵逼,直到在网上看了一些大佬的解释,才慢慢开始理解,正如上面所说的,第三条规则与第二条规则需要结合起来看,如果aPbTc是正确的能推导出什么结论呢?看第二条规则,形如xPATx均正确,其中x为空串或者仅由A组成的字符串。如果aPbTc是正确的,由第二条规则可知,b = A,a = c,再往下看,那么aPbATca也是正确的,仔细观察,PT之间多了一个a,相应的T右边多了一个a,也就是说aPT之间每有一个A,那么T右边就相应的多一个a,如此看来,xPATx就可以看做是中间有一个A的情况,即xPATx --> aPATa,所以,综合起来看,由于规则1限制了字符的种类,所以T右边A的个数就等于P左边A的个数乘以PT中间A的个数,此时字符串正确,反之错误。
  • 总之一句话,P前面A的个数 * PT之间A的个数 = T后面A的个数且PT之间至少有一个A,最后切记!!!P要在T的前面,这一点困扰了我很长时间,直到看见了一个兄弟博客才恍然大悟  答案正确  。

代码实现:

/*	答案正确的条件 
*	1.仅含P、A、T三种字符
*	2.P、T之间至少有一个A且P、T顺序固定
*	3.(P左侧A的数量) * (PT之间A的数量) = (T右侧A的数量) 
*/

#include <stdio.h>

int main()
{
	int n = 0;	
	int answer[10] = { -1 };		//字符串的判决结果,10是因为n < 10,0:NO,1:YES,-1:初始状态 
	int index = 0;					//index = 0,累加的P左边A的个数,index = 1,累加的是PT中间A的个数,index = 2,累加的是T右边A的个数 
	int count1 = 0;					//P左边即a中A的个数 
	int count2 = 0;					//PT中间A得个数
	int count3 = 0;
	int j = 0;
	char str[101];
			
	scanf("%d", &n);
	getchar();						//吃掉回车			
	
	for(int i = 0; i < n; i++)
	{
		gets(str);

		while(1)
		{
			if(str[j] == 'P' || str[j] == 'A' || str[j] == 'T')//正常情况下仅有P、A、T 
			{
				if((str[j] == 'P' && index == 0) || (str[j] == 'T' && index == 1))//正常情况下index = 2,若index != 2,错误,切记要保证P在T的前面 
				{ 
					index++;
				} 
				else//累加A的个数 							
				{
					switch(index)	
					{
						case 0: count1++; break;
						case 1: count2++; break;
						case 2: count3++; break;
						default: break;
				 	}	 
					
				}
			} 
			else
			{
				if(str[j] == '\0')//回车符 
				{
					if(count3 == (count1 * count2) && index == 2 && count2 >= 1)//注意PT之间至少有一个A 
						answer[i] = 1;
					else 
						answer[i] = 0;
				}
				else//其他字符直接判NO
				{
					answer[i] = 0;
				} 
					
				break; 
			}
				
			j++;
		}				
		count1 = count2 = count3 = index = j = 0;//莫要忘记变量归零 
	}	
	
	for(int i = 0; i < n; i++)
	{
		switch(answer[i])
		{
			case 1: printf("YES\n"); break;
			default: printf("NO\n"); break;
		}
	}
	
	return 0;
}

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!