洛谷P1039 [NOIP2003 提高组] 侦探推理
Problem
Solve
较为快速且好想的暴力方法是枚举m个人中选n个的组合方案,然后对证词进行检验,时间复杂度\(O(\frac{m!}{n!^2}p)\),仔细算算竟然能够在2e8左右通过
但实际上这道题在当年肯定是给不了你2e8/sec的算力的,这道题目能够评蓝我觉得上面方法肯定是不配的
结合€€£在18年及以前的4e6/sec祖传老爷机,我们需要换一种方法。
可以观察到,我们在枚举组合的时候往往因为一个小小的改动而重新枚举p,这样肯定不优,我们可以换种角度:
每次枚举真相可能的结果,将结果代入证词进行检验,计算一下在这种情况有多少人说假话即可,时间复杂度\(O(dnp)\),d是星期的总数,为7
这样就能过掉了,感觉根本没有蓝的难度。
PS:其实还有一种方法能把d优化掉,但是很麻烦,不建议写(直接枚举凶手,根据初步得到的嫌疑人信息推理可能的星期)
Code
#include<bits/stdc++.h> using namespace std; int n,m,p,w[105],f[105];//0:UB 1~7:Monday~Sunday 8/9: 2idx/2idx+1: string name[25],ans; map<string,int> b,day; void init(){ day["Monday."]=1,day["Tuesday."]=2,day["Wednesday."]=3,day["Thursday."]=4; day["Friday."]=5,day["Saturday."]=6,day["Sunday."]=7; } int main(){ init(); cin>>n>>m>>p; for(int i=1;i<=n;i++){ cin>>name[i]; b[name[i]]=i; } string tmp,t,word[255]; int cnt=0; getline(cin,t); for(int i=1;i<=p;i++){ getline(cin,t); t.erase(t.size()-1,1);//The problem's case was made in windows tmp="",t+=" "; cnt=0; for(int j=0;j<t.size();j++){ if(t[j]!=' ')tmp+=t[j]; else{ word[++cnt]=tmp; tmp=""; } } w[i]=b[word[1].substr(0,word[1].size()-1)]; if(cnt==4){ if(word[2]=="I"&&word[3]=="am"&&word[4]=="guilty."){ f[i]=8; } if(word[3]=="is"&&word[4]=="guilty."){ f[i]=10*b[word[2]]; } if(word[2]=="Today"&&word[3]=="is"){ f[i]=day[word[4]]; } }else if(cnt==5){ if(word[2]=="I"&&word[3]=="am"&&word[4]=="not"&&word[5]=="guilty."){ f[i]=9; } if(word[3]=="is"&&word[4]=="not"&&word[5]=="guilty."){ f[i]=10*b[word[2]]+1; } } } for(int i=1;i<=n;i++){ for(int j=1;j<=7;j++){ int cntf=0,cnth=0,c[25]; memset(c,0,sizeof(c)); for(int k=1;k<=p;k++){ if(!f[k])continue; if(f[k]==j||f[k]==i*10||f[k]==8&&w[k]==i||f[k]==9&&w[k]!=i||f[k]>=10&&f[k]%10==1&&f[k]/10!=i){ if(c[w[k]]==-1){ cntf=0x3f3f3f3f; break; } if(c[w[k]]==1){ continue; } cnth++; c[w[k]]=1; }else{ if(c[w[k]]==1){ cntf=0x3f3f3f3f; break; } if(c[w[k]]==-1){ continue; } cntf++; c[w[k]]=-1; } } if(cntf<=m&&cntf+(n-cnth-cntf)>=m){ if(ans==""){ ans=name[i]; break; }else{ cout<<"Cannot Determine"; return 0; } } } } if(ans=="")cout<<"Impossible"; else cout<<ans; return 0; }
本文作者:yiweixxs
本文链接:https://www.cnblogs.com/yiweixxs/p/18582893
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步