(PAT乙级)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

题目解析:

第一遍看题目把空字符串理解为空格了。。走了很多的弯路,最后才理解到只含有PAT三个字符串,那么问题就简化很多了。

首先最基本的形式为xxPATxx,PAT前后一定保证A的数量是一样的,如果没有A那就是“PAT"即为最简单的形式;

那么再看第三种,aPbATca这种形式若要成立的话,那么最后递归的结果一定是中间只有一个A,P前面的A数量与T后面的A数量一致,那么我们就可以归纳出P前面的A数量a与PT中间的A数量b还有与T后面的A数量ac的关系为:a*b=ac;

到这里我们发现所有的三种条件都满足这个关系式,因此我们可以按照这个方法敲出如下C++代码:

PS:其实这道题目的测试案例挺不严谨的,既没有判断P和T的位置关系,也没有判断P和T的数量问题,默认就是P在T前,而且只有一个PT...

#include <iostream>
#include <string>
using namespace std;

bool pass(string s)
{
	int flagp, flagt;
	int countp = 0, countt = 0;//P的位置,T的位置
	int len;  //字符串的长度
	len = s.size();
	for (int j = 0; j < len; j++)
	{
		switch (s[j])
		{
		case'A':
			break;
		case'P':
			flagp = j;
			break;
		case'T':
			flagt = j;
			break;
		default:
			return false;
		}
	}
	if (((flagp - 0)*(flagt - flagp - 1) != (len - 1 - flagt)) ||((flagt - flagp) == 1))//上文推断的判断公式,如果中间没有A也是错的,所以要用flagt-flagp;
		return false;
	else
		return true;
}
int main()
{
	int n;

	cin >> n;
	string *s = new string[n];
	for (int i = 0; i < n; i++)
	{
		cin >> s[i];
	}
	for (int i = 0; i < n; i++)
	{
		if (pass(s[i]))
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}

如果你推不出来上面那个判断公式的话,我这有一个特别笨的方法...为了纪念弯路还是贴上来吧

#include <iostream>
#include <string>
using namespace std;

bool pass(string s)
{
	int flagp, flagt;
	int countp=0,countt=0;//P的位置,T的位置
	int len;//字符串的长度
	len = s.size();
	for (int j = 0; j < len; j++)
	{
		switch (s[j])
		{
		case'A':
			break;
		case'P':
			flagp = j;
			countp++;
			if (countp>1) return false;
			break;
		case'T':
			flagt = j;
			countt++;
			if (countt > 1) return false;
			break;
		default:
			return false;
		}
	}
	if (((flagt - flagp) == 1)||(flagp>flagt)) return false;//确定PT位置是否合理
	if (flagp != 0)//pat前面有字符
	{
		for (int j = 0; j < flagp; j++)
		{
			if (s[j] != s[0])
				return false;
		}
		for (int k = flagt + 1; k < len; k++)
		{
			if (s[k] != s[0])
				return false;
		}
	}
	for (int j = flagp + 1; j < flagt; j++)//判断pat中间部分
	{
		if (s[j] != 'A') return false;
	}
	string tmp;
	while(flagt - flagp >= 3)//中间超过两个A
	{
		tmp = "";
		for (int j = 0; j < flagt-1; j++)//字符串前面不动,中间A减少一个
			tmp = tmp + s[j];
		tmp = tmp + 'T';
		for (int j = 0; j < (len - flagt - 1-flagp); j++)//len-flag-1是c+a的长度,再减去flagp的长度就只剩下c的长度了
			tmp = tmp + 'A';
		flagt--;
		len = tmp.size();
	}
	if (flagp == (len - flagt - 1))
		return true;
	else
		return false;
}
int main()
{
	int n;
	
	cin >> n;
	string *s=new string[n];
	for (int i = 0; i < n; i++)
	{
		cin >> s[i];
	}
	for (int i = 0; i < n; i++)
	{
		if (pass(s[i]))
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yuquan87/article/details/80098360