题目背景
国际象棋在对局时,同一局面连续或间断出现3次或3次以上,可由任意一方提出和棋。
问题描述
国际象棋每一个局面可以用大小为 8×8 的字符数组来表示,其中每一位对应棋盘上的一个格子。六种棋子王、后、车、象、马、兵分别用字母 k
、q
、r
、b
、n
、p
表示,其中大写字母对应白方、小写字母对应黑方。棋盘上无棋子处用字符 *
表示。两个字符数组的每一位均相同则说明对应同一局面。
现已按上述方式整理好了每步棋后的局面,试统计每个局面分别是第几次出现。
注意点
这个棋局可以允许同种棋子在不同位置出现,所以我用list存储位置信息。
#include<iostream>
#include<map>
#include<tuple>
#include<list>
#include<algorithm>
using namespace std;
int Count(list<map<char, list<tuple<int, int>>>> chess_games, map<char, list<tuple<int, int>>> m1);
int main()
{
int n;
cin >> n;
char c;
map<char, list<tuple<int, int>>> m1;
list<map<char, list<tuple<int, int>>>> chess_games;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 8; k++)
{
cin >> c;
if (c == '*') continue;
else m1[c].push_back(tuple<int,int>(j, k));
}
}
chess_games.push_back(m1);
cout << Count(chess_games, m1) << endl;
m1.clear();
}
}
int Count(list<map<char, list<tuple<int, int>>>> chess_games, map<char, list<tuple<int, int>>> m1)
{
int count = 0;
/*
其实可以用序号来表示,但是自己已经麻烦了就麻烦到底吧
依次去比对有点麻烦了,占空间了
遍历m1,找它的键值会好点吧。
*/
for (map<char, list<tuple<int, int>>> a : chess_games) { //遍历所有棋局
if (a.size() != m1.size()) continue; //棋子种类不对直接下局
bool flag = true;
for (pair<char, list<tuple<int, int>>> b : m1) //遍历棋子
{
for (tuple<int, int>c : b.second) { //遍历棋子所有存在的位置
if (find(a[b.first].begin(), a[b.first].end(), c) == a[b.first].end())
{
flag = false;
break;
}
}
if (!flag)
break;
}
if (flag)
count++;
}
return count;
}