Tournament Chart
传送门:链接 来源:UPC10889
题目描述
In 21XX, an annual programming contest, Japan Algorithmist GrandPrix (JAG) has become one of the most popular mind sports events.
JAG is conducted as a knockout tournament. This year, N contestants will compete in JAG. A tournament chart is represented as a string. '[[a-b]-[c-d]]' is an easy example. In this case, there are 4 contestants named a, b, c, and d, and all matches are described as follows:
Match 1 is the match between a and b.
Match 2 is the match between c and d.
Match 3 is the match between [the winner of match 1] and [the winner of match 2].
More precisely, the tournament chart satisfies the following BNF:
<winner> ::= <person> | "[" <winner> "-" <winner> "]"
<person> ::= "a" | "b" | "c" | ... | "z"
You, the chairperson of JAG, are planning to announce the results of this year's JAG competition. However, you made a mistake and lost the results of all the matches. Fortunately, you found the tournament chart that was printed before all of the matches of the tournament. Of course, it does not contains results at all. Therefore, you asked every contestant for the number of wins in the tournament, and got N pieces of information in the form of "The contestant ai won vi times".
Now, your job is to determine whether all of these replies can be true.
输入
The input consists of a single test case in the format below.
S
a1 v1
:
aN vN
S represents the tournament chart. S satisfies the above BNF. The following N lines represent the information of the number of wins. The (i+1)-th line consists of a lowercase letter ai and a non-negative integer vi (vi≤26) separated by a space, and this means that the contestant ai won vi times. Note that N (2≤N≤26) means that the number of contestants and it can be identified by string S. You can assume that each letter ai is distinct. It is guaranteed that S contains each ai exactly once and doesn't contain any other lowercase letters.
输出
Print 'Yes' in one line if replies are all valid for the tournament chart. Otherwise, print 'No' in one line.
样例输入
[[m-y]-[a-o]]
o 0
a 1
y 2
m 0
样例输出
Yes
题目大意:
给出上面的BNF公式(看不懂),猜测应该是一个公式类似: [ [a-b]-c ] (这个比样例有普遍性)
每个 - 代表前面的队伍要和后面的队伍比赛,获胜的再与后面的比,在上面的例子中,是a先与b比赛,获胜者再与c比。
题目给出每个队伍最终的获胜次数,让你判断这个数据有没有可能是正确的。
解题思路:
按照下图一步步模拟就行了,因为要用到删除操作,直接用string不太好实现,可以用 vector<char>,这篇博很详细:传送门 。
具体实现就是每次遍历vector,找到两边都是字母的减号,删除【vc[i-2],vc[i+2]】的内容,再把胜场多的字符插入进去(也可以先修改字符再删内容,只是区间要变化一下),并将他对应的胜场-1(map数组在这很好用)。
判断条件:
两个比赛队伍,肯定会有一个会输,也就是胜场为0,否则就输出NO。
如果两个比赛的队伍胜场相同,也要输出NO。
最后只剩下的一个队伍对应的胜场应该也是0,否则输出NO。
AC代码:
感谢队友给找的bug:https://me.csdn.net/qq_43559193
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a;
cin>>a; ///输入字符串
int la=a.size(),cnt=0;
for(int i=0;i<la;i++){
if(a[i]>='a'&&a[i]<='z'){
cnt++;
}
}
vector<char>vc;
for(int i=0;i<la;i++){ ///字符串内容赋值到vector中(输入的时候直接往里面存也可以)
vc.push_back(a[i]);
}
map<char,int>mp;
for(int i=0;i<cnt;i++){ ///输入胜场,存入mp数组
int num;
char id;
cin>>id>>num;
mp[id]=num;
}
while(vc.size()!=1){
for(int i=0;i<vc.size();i++){
if(vc[i]=='-'&&vc[i-1]>='a'&&vc[i-1]<='z'&&vc[i+1]>='a'&&vc[i+1]<='z'){
if(!(mp[vc[i+1]]==0||mp[vc[i-1]]==0)||(mp[vc[i+1]]==mp[vc[i-1]])){
cout<<"No"<<endl; ///一定要判断,不然会死循环
return 0;
}
if(mp[vc[i+1]]>mp[vc[i-1]]){ ///减号右边的胜场多
vc[i+2]=vc[i+1];///先修改值
mp[vc[i+1]]--;
vc.erase(vc.begin()+i-2,vc.begin()+i+2); ///删除区间内容
break;
}else if(mp[vc[i+1]]<mp[vc[i-1]]){///减号左边的胜场多
vc[i+2]=vc[i-1];
mp[vc[i-1]]--;
vc.erase(vc.begin()+i-2,vc.begin()+i+2);
break;
}
}
}
}
if(mp[vc[0]]==0) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}