Codeforces Round #390 (Div. 2)C Vladik and chat

題目大意:

       有n個人和m句話,有些話的說話人不明,要求是每個人不能連着說兩句話,每句話不能提到自己,看看能不能將這些話的說話人都找出來,答案可能不固定。

解題思路:

       根據題目意思將問題簡化,建立dp[i][j]意思爲第 j 句話可能是 i 說的,首先明確說話人的話,將已知的說話人作爲唯一的可能對象,其他的話只要不是提到的人都作爲可能對象。接下來其實就是dfs找一條結果樹,只要滿足相鄰兩句話不是一個人說的就行了,但是直接爆搜的複雜度有點大,可以使用記憶化搜索,記錄所有可能解。最後輸出就好了。

代碼:

#include "iostream"
#include "cstdio"
#include "math.h"
#include "algorithm"
#include "string"
#include "string.h"
#include "vector"
#include "map"
#include "queue"
#include "assert.h"
using namespace std;
int T, n, m, memo[105][105], retuser[105];
string name[105], message[105];
bool dp[105][105];//false:j may be say message i
bool isok(char c) {
	if ((c >= '0'&&c <= '9') || (c >= 'a'&&c <= 'z') || (c >= 'A'&&c <= 'Z'))
		return true;
	return false;
}
int cal(int id, int bef) {
	if (id > m)
		return memo[id][bef] = 1;
	int &ret = memo[id][bef];
	if (ret != -1)
		return ret;
	ret = 0;
	for (int i = 1;i <= n;i++) {
		if (!dp[id][i] && bef != i) {
			ret = max(ret, cal(id + 1, i));
		}
	}
	return ret;
}
int main() {
	scanf("%d", &T);
	while (T--) {
		memset(dp, 0, sizeof(dp));
		scanf("%d", &n);
		map<string, int>mp;
		for (int i = 1;i <= n;i++) {
			cin >> name[i];
			mp[name[i]] = i;
		}
		scanf("%d", &m);
		getchar();
		for (int i = 1;i <= m;i++) {
			getline(cin, message[i]);
			int len = message[i].length();
			string temp = "";
			if (message[i][0] != '?') {
				for (int k = 0;k < len;k++) {
					if (isok(message[i][k]))
						temp += message[i][k];
					else
						break;
				}//get the speaker's name
				for (int k = 1;k <= n;k++)
					dp[i][k] = true;
				dp[i][mp[temp]] = false;
			}
			else {
				for (int k = 0;k < len;k++) {
					if (isok(message[i][k]))
						temp += message[i][k];
					else {
						int id = 0;
						if (mp.count(temp))
							id = mp[temp];
						dp[i][id] = true;
						temp.clear();
					}
				}
				int id = 0;
				if (mp.count(temp))
					id = mp[temp];
				dp[i][id] = true;
			}
		}
		memset(memo, -1, sizeof(memo));
		int ret = cal(1, 0);
		if (ret != 1)
			puts("Impossible");
		else {
			int user;
			for (int i = 1;i <= n;i++) {
				if (memo[m + 1][i] == 1) {
					user = i;
					break;
				}
			}
			int id = m;
			while (1) {
				retuser[id] = user;
				if (id == 1)
					break;
				for (int i = 1;i <= n;i++) {
					if (user != i&&memo[id][i] == 1) {
						user = i;
						break;
					}
				}
				id--;
			}
			for (int i = 1;i <= m;i++) {
				cout << name[retuser[i]];
				int j;
				for (j = 0;j < message[i].size();j++)
					if (message[i][j] == ':')
						break;
				while (j < message[i].size())
					putchar(message[i][j++]);
				puts("");
			}
		}
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章