SanguoSHA
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1246 Accepted Submission(s):
685
Problem Description
Sanguosha has a singled version. Two
players each select N heroes and start fighting. If a hero dies, the next
follows. If one player's heroes are all dead, he loses.
There're restraints among heroes. For example, YuJi restricts Zhu Geliang, LuXun restricts DaQiao, ZhangJiao restricts MaChao, WeiYan restricts XiaoQiao.
Today I play with friends. I know the heroes and the restraints.(If opponent's hero restraint my hero, my hero will be beaten, others my hero will beat opponent's hero)
Can you arrange my heroes' order,no matter what order of opponent's heroes, so that I can win the game?
There're restraints among heroes. For example, YuJi restricts Zhu Geliang, LuXun restricts DaQiao, ZhangJiao restricts MaChao, WeiYan restricts XiaoQiao.
Today I play with friends. I know the heroes and the restraints.(If opponent's hero restraint my hero, my hero will be beaten, others my hero will beat opponent's hero)
Can you arrange my heroes' order,no matter what order of opponent's heroes, so that I can win the game?
Input
The first line is a number T(1<=T<=50),
represents the number of case. The next T blocks follow each indicates a
case.
The first line is N(3<=N<=6).
The second line has N names(shorter than 20 letter).
The following N lines each contains a restraints. Restraints are given as “k b1 b2 … bk”, which means the opponent's hero restricts my hero b1, b2 … bk. (0<=K<=N)
The first line is N(3<=N<=6).
The second line has N names(shorter than 20 letter).
The following N lines each contains a restraints. Restraints are given as “k b1 b2 … bk”, which means the opponent's hero restricts my hero b1, b2 … bk. (0<=K<=N)
Output
For each case, first line output the number of case
with "Yes" or "No". If Yes, output the order of your heroes separate by a space.
If there are more than one order, please output the one with minimum
lexicographic order.(as shown in the sample output)
Sample Input
2
3
ZhugeLiang HuangYueying ZhenJi
1 ZhugeLiang
2 HuangYueying ZhenJi
2 ZhugeLiang ZhenJi
4
MaChao YanLiangWenChou YuJin XiaoQiao
2 MaChao XiaoQiao
2 YanLiangWenChou YuJin
1 XiaoQiao
0
Sample Output
Case 1: No
Case 2: Yes
MaChao YanLiangWenChou XiaoQiao YuJin
题意:三国杀1v1,双方都有N张武将牌,武将牌之间有克制的关系,一方的武将牌要么被对方克制,要么克制对方,一旦武将牌被对方克制,该武将就会战败,换下一张武将牌继续打;否则,一直战斗,直到该武将战败或者对方没有武将了为止。
现在要求你找出一种组合,使得无论对方怎么排列自己的武将牌顺序,你都将立于不败之地,如果有多种情况,则输出武将名字的字典序最小的情况。
思路:
排列组合,暴力枚举,对于我方的每一种可能的武将出场顺序组合,穷尽对方的每一种武将牌出场顺序,如果都被我方当前的武将牌出场顺序所打败,那么这种出场顺序是可行的,找到字典序最小的组合即可。
AC代码:
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<set> #include<string> #include<map> using namespace std; const int N_MAX = 6; string s[N_MAX]; set<string>Set[N_MAX]; int main() { int T,t=0; scanf("%d",&T); while (T--) { t++; int N; scanf("%d",&N); for (int i = 0; i < N; i++) { cin >> s[i]; } sort(s, s + N);//以字典序从小到大排 for (int i = 0; i < N; i++) { int num; scanf("%d",&num); for (int j = 0; j < num; j++) { string ss; cin >> ss; Set[i].insert(ss); } } sort(Set, Set + N);//!!!!字典序排列 bool flag = 0; int a=0; do{//对于每一种武将排列的组合,判断一下是否符合要求 flag = 1; do {//无论对方的牌怎么换,都要成功打败才可以 int i = 0; int ant = 0; while (i <N && ant<N) { set<string>::iterator it = Set[i].find(s[ant]);//在集合中找有没有克制武将s[ant]的 if (it != Set[i].end()) {//该武将被克制了 ant++;//换下一个武将 } else { i++;//挑战下一位 } } if (i<N) { flag = 0; break; }//失败 } while(next_permutation(Set,Set+N));//从最小字典序开始考虑每一种排列 if (!flag) {//!!!!!!上一次失败了,为了下一次继续运行Set的排列组合时从最小字典序开始,就要归位 while (prev_permutation(Set, Set + N)); next_permutation(Set, Set + N); }//!!! if (flag)break;//成功 } while (next_permutation(s, s + N)); if (flag) { printf("Case %d: Yes ", t); for (int i = 0; i < N; i++) { if(i==0)cout << s[i] ; else cout <<" "<< s[i]; } printf(" "); } else printf("Case %d: No ",t); for (int i = 0; i < N;i++) { Set[i].clear(); } } return 0; }