Codeforces Round #390 (Div. 2) C. Vladik and chat (DP/记忆化搜索)

来源:互联网 发布:2017流行语言网络语言 编辑:程序博客网 时间:2024/06/11 08:55

题意

有n个人和m句话,有些话的说话人不明,要求是每个人不能连着说两句话,每句话不能提到自己,看看能不能将这些话的说话人都找出来,答案可能不固定。

思路

题目的限制只有两个,因此对于每一句说话人不明的话,可以直接枚举可能的说话人,但是暴力搜索复杂度太高,因此可以使用动态规划或者记忆化搜索来求解。因为一个人不能连着说两句话,所以当前枚举的说话人会影响到后面的结果,由于题目只要求任意可行解,我们要做的就是找出一条可行路径
定义par[i][j]=k表示到第i句话为止都可行,并且第i句话是第j个人说的,前面一句话是第k个人说的

代码

#include <bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))#define rep(i,a,b) for(int i=a;i<b;i++)#define debug(a) printf("a =: %d\n",a);const int INF=0x3f3f3f3f;const int maxn=3e5+50;const int Mod=1000000007;const double PI=acos(-1);typedef long long ll;typedef unsigned int ui;using namespace std;bool ok[233][233];int par[233][233];string msgs[233];string ans[233];string users[233];map<string,int> ma;int m,n;bool getAns(){    int pos=m-1;    for(int i=0;i<n;i++){        if(par[pos][i]!=-1){            int cur=i;            while(pos>=0){                ans[pos]=users[cur];                cur=par[pos][cur];                pos--;            }            return true;        }    }    return false;}vector<string> split(string &s){    vector<string> ret;    string token="";    for(char c:s){        if(isalpha(c) || isdigit(c)) token+=c;        else {            if(!token.empty()) ret.push_back(token);            token="";        }    }    if(!token.empty()) ret.push_back(token);    return ret;}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);#endif    int T; scanf("%d",&T);    while(T--){        ma.clear();        scanf("%d",&n);        string s;        for(int i=0;i<n;i++) {            cin>>s;            users[i]=s;            ma[s]=i;        }        scanf("%d",&m);        getchar();        mem(ok,0);        for(int i=0;i<m;i++){            getline(cin,s);            int pos=s.find(':');            msgs[i]=s.substr(pos);            ans[i]=s.substr(0,pos);            if(ans[i]=="?"){                vector<string> sp=split(msgs[i]);                for(int j=0;j<n;j++) ok[i][j]=true;                for(string ss:sp){                    if(ma.find(ss)!=ma.end())                        ok[i][ma[ss]]=false;                }            }else{                ok[i][ma[ans[i]]]=true;            }        }        mem(par,-1);        for(int i=0;i<m;i++){            for(int j=0;j<n;j++){                if(ok[i][j]){                    if(i==0) par[i][j]=-2;                    else{                        for(int k=0;k<n;k++){                            if(k!=j && par[i-1][k]!=-1){                                par[i][j]=k;                                break;                            }                        }                    }                }            }        }        if(getAns()){            for(int i=0;i<m;i++){                printf("%s%s\n",ans[i].c_str(),msgs[i].c_str());            }        }else puts("Impossible");    }    return 0;}
0 0
原创粉丝点击