• 【洛谷1039】侦探推理(字符串模拟题)


    点此看题面

    • (m)个人,其中有一个罪犯。已知(n)个人始终说假话,其余人始终说真话。
    • (p)句证词,分下列五种格式:(不属于任何格式的证词需要忽略)
      • I am guilty.:我是罪犯。
      • I am not guilty.:我不是罪犯。
      • XXX is guilty.:XXX是罪犯。
      • XXX is not guilty.:XXX不是罪犯。
      • Today is XXX.:今天是XXX。其中XXX为Monday~Sunday
    • 需要找出谁是罪犯,或判断无解或有多种可能。
    • (mle20,ple100,|S|le250)

    字符串模拟

    直接枚举谁是罪犯,今天是星期几,判断始终说假话人数是否小于等于(n),始终说真话人数是否小于等于(m-n)。(之所以这么判是因为可能有只说废话或不说话的人)

    判断显然是很简单的,主要涉及一些对字符串的操作。因此这里简单记录一下通过这题学到的几种字符串函数用法:

    • getline(cin,s):读入字符串(s)
    • s.erase(p,l):从(s)(p)个字符开始删去(l)个字符。
    • s.substr(p,l):返回从(s)(p)个字符开始连续(l)个字符构成的子串。

    代码:(O(mp))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define M 20
    #define P 100
    #define S 250
    using namespace std;
    const string Day[7]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
    int m,n,p,u[P+5],f[M+5];string g[M+5],w[P+5],s[P+5];map<string,int> id,dt;
    I bool U(CI id,bool v) {return id?(f[id]==(v^1)?0:(f[id]=v,1)):1;}//id说话的真假性为v,判是否矛盾
    int main()
    {
    	RI i;for(i=0;i^7;++i) dt[Day[i]]=i;
    	for(scanf("%d%d%d",&m,&n,&p),i=1;i<=m;++i) cin>>g[i],id[g[i]]=i;
    	for(i=1;i<=p;++i) cin>>w[i],u[i]=id[w[i].substr(0,w[i].size()-1)],
    		getline(cin,s[i]),s[i].erase(0,1),s[i].erase(s[i].size()-1,1);//注意,因为线上评测问题,getline会多读入一个
    ,需要删去末尾字符
    	RI j,k,t0,t1,ans=0;for(i=1;i<=m;++i) for(j=0;j^7&&ans^i;++j)//枚举罪犯是谁,今天是星期几
    	{
    		for(k=1;k<=m;++k) f[k]=-1;for(k=1;k<=p;++k)//枚举每一句证词
    		{
    			if(s[k]=="I am guilty."&&!U(u[k],u[k]==i)) goto End;//我是罪犯
    			if(s[k]=="I am not guilty."&&!U(u[k],u[k]^i)) goto End;//我不是罪犯
    			if(s[k].size()>10&&s[k].substr(s[k].size()-11,11)==//XXX是罪犯
    				" is guilty."&&!U(u[k],id[s[k].substr(0,s[k].size()-11)]==i)) goto End;
    			if(s[k].size()>14&&s[k].substr(s[k].size()-15,15)==//XXX不是罪犯
    				" is not guilty."&&!U(u[k],id[s[k].substr(0,s[k].size()-15)]^i)) goto End;
    			if(s[k].size()>10&&s[k].substr(0,9)=="Today is "&&//今天是XXX
    				dt.count(s[k].substr(9,s[k].size()-10))&&!U(u[k],dt[s[k].substr(9,s[k].size()-10)]==j)) goto End;
    		}
    		for(t0=t1=0,k=1;k<=m;++k) !f[k]&&++t0,f[k]==1&&++t1;if(t0>n||t1>m-n) goto End;//如果始终说假话/真话人数不符
    		if(ans) return puts("Cannot Determine"),0;ans=i;End:;//判多种可能
    	}return ans?(cout<<g[ans]<<endl,0):puts("Impossible"),0;//判无解
    }
    
  • 相关阅读:
    python发送邮件
    常用的排序算法
    关于前端ajax请求url为何添加一个随机数
    RabbitMQ消息队列
    shell编程基本语法和变量
    第70课 展望:未来的学习之路(完结)
    第69课 技巧:自定义内存管理
    第68课 拾遗:让人迷惑的写法
    第67课 经典问题解析五
    第66课 C++中的类型识别
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu1039.html
Copyright © 2020-2023  润新知