2021年PAT乙级B-3 自定义判题程序 (20 分) 题型:大模拟

97 阅读4分钟

B-3 自定义判题程序 (20 分)

在每次允许插入、删除、修改一个字符的前提下,用最少的动作把一个字符串变成另一个字符串,是一道著名的可以用动态规划解决的问题。但判题的麻烦之处在于,虽然最小代价是唯一的,但变换方法却是不唯一的。例如把 PAT 变成 PTA 最少需要 2 步,可以保持第 1 个字母不变,修改后面 2 个字母,也可以保持第 1、2 个字母不变,在 A 前面插入 T,后面删除 T。由于拼题 A 系统的默认判题程序只能通过比对输出文件来判断对错,对这种正确答案输出不唯一的题目就不能处理了,需要出题者额外编写一个自定义判题程序来解决问题。

本题就请你编写这个自定义判题程序,读入两个字符串和用户程序产生的输出结果,判断他们的程序输出是否正确。

输入格式

输入首先在前两行分别给出两个不超过 1000 个字符、以回车结束的非空字符串,第 1 行对应初始字符串,第 2 行对应目标字符串。

随后一行给出一个正整数 N(≤100),为需要判断的提交数。

接下来是 N 个提交的输出结果,每个结果占 2 行:第 1 行给出一个整数 K(不超出 32 位 int 的范围),为用户输出的动作数;第 2 行顺次描述对初始字符串的每个字符所做的操作:

  • 如果这个字符不变,则在对应位置输出 0
  • 如果这个字符被删除,则在对应位置输出 1
  • 如果这个字符被改变,则在对应位置输出 2
  • 如果这个字符前面或者后面插入了一个字符,则在插入的位置输出 3

注意我们要求用户提交的行首尾和数字间均无空格,所以如果有多余空格应判为错误。

题目保证这个操作序列不为空。

输出格式:

对每个正确的提交,在一行中输出 AC;否则输出 WA。

注意:这里并不要求你会用动态规划求出最优解。所以对“正确提交”的判断,并不以动态规划求出的最优解为根据! 对于用户输出的 K,如果其操作序列的确给出了 K 步操作并可以完成字符串的变换,则称为一个“可行解”。所谓“正确提交”,是指所有提交的可行解中的最优解。

输入样例:

This is a test.
Tom is a cat.
6
8
02330001100022100
8
11113330000001113300
6
022100000012200
5
033310000000200
6
0 2 2 1 000000 1 2 2 00
6
012200000022100

WA
WA
AC
WA
WA
AC

code

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int t,K[11000];   //t组测评,k存放每组测评的结果 
	string a,b,s;     //源字符串,目的字符串 ,操作符 
	int minn=0x3f3f3f3f;
	getline(cin,a);
	getline(cin,b);
    cin>>t;
	
	for(int z=0;z<t;z++)
	{
		int k,j=0,flag=0,cnt=0;
		cin>>k;  //k代表输入的有效操作数 
	    string c;
	    getchar();
		getline(cin,s);  //输入操作符
		
		for(int i=0;i<s.size();i++)
		{
		  if(s[i]=='0')  //什么都不操作 
	      {
	      	c+=a[j];     //加原字符 
	      	j++; 
		  }
		  else if(s[i]=='1')  //删除操作 
		  {
		  	j++;              //直接跳过当前字符 
		  	cnt++;
		  }
		  else if(s[i]=='2')  //修改 
		  {
		    c+='^';    //^是万能字符,后续判断时直接判断正确	
		    j++;
			cnt++; 
		  } 
	      else if(s[i]=='3')  //插入操作 
	      {
	      	c+='^';          //直接插入,插入完j还指向原位 
			cnt++; 
		  }
		  else
		  {
		    flag=1;  //出现了0,1,2,3之外的字符都是非法	
		  } 
		}
		
		if(c.size()!=b.size()&&cnt!=k) flag=1;   //判断一下字符串是否相等 
		 
	    for(int i=0;i<b.size();i++)
		{
			if(c[i]==b[i]||c[i]=='^')continue;  //字符相等或者是万能符是合法情况,直接通过
			else flag=1; 
		}
		if(!flag)             //对于合法情况 
		{
			K[z]=k;
			if(k<minn)minn=k;  //记录最小操作步数 
		}
		else  //非法情况 
		{
			K[z]=-1;   //记录错误 
		} 
	}
	
	for(int i=0;i<t;i++)
	{
	   if(K[i]==minn)cout<<"AC"<<endl;
	   else cout<<"WA"<<endl;	
    }
	return  0;
}