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

来源:互联网 发布:电话号码模拟软件 编辑:程序博客网 时间:2024/05/20 02:27

题目大意:

       有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 ibool 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];elsebreak;}//get the speaker's namefor (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;}

0 0
原创粉丝点击