Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

暴力枚举+模拟,有点繁琐,内附代码+报告

Posted by liuyuhong at 2015-12-06 21:00:04 on Problem 1478
直接暴力,代码写得有点挫。。。
我的报告:http://blog.csdn.net/viphong/article/details/50198029

下面是代码+详细注释

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std; 
struct node
{
	char spker;
	char who;
	int is_not;
	string what;
	int d_or_n;
};
node tm[55];

string ss;  

vector<int> sb[55];
set<char> ::iterator it;
int main()
{
	
	int n,i;
	int cnt=1;
	set<char> sb;
	while(scanf("%d",&n)!=EOF&&n)
	{
		sb.clear();
		getchar();
		for (i=1;i<=n;i++)
		{
			getline(cin,ss);
			string sub=ss.substr(3,ss.length()-3);		//截取除去主语后的一句话
			tm[i].d_or_n=-1;			// 为-1表示本句话与时间无关
			if (sub=="It is day.")
			{  
				tm[i].spker=ss[0];				//记下说话人
				tm[i].d_or_n=1;continue;		//记下是白天还是黑夜
			}
			if (sub=="It is night.")
			{  
				tm[i].spker=ss[0];
				tm[i].d_or_n=0;continue;
			} 
			if (ss[3]=='I')			//‘I’就是说话人自己
				ss[3]=ss[0];
			tm[i].spker=ss[0];
			tm[i].who=ss[3];
			sb.insert(tm[i].spker);		//计算种类
			sb.insert(tm[i].who);
			if (ss.find("not")!=string::npos)	//如果找不到not,则为肯定句,找到则表示为否定句
				tm[i].is_not=0;
			else
				tm[i].is_not=1;
			if (ss.find("divine")!=string::npos)		//被认为是什么
				tm[i].what="divine";
			else	if (ss.find("human")!=string::npos)
				tm[i].what="human";
			else	if (ss.find("evil")!=string::npos)
				tm[i].what="evil";
			else	if (ss.find("lying")!=string::npos)
				tm[i].what="lying"; 
		}
		
		printf("Conversation #%d\n",cnt++);		
		
		string what[6];		//what[i]存第i个人 当前的身份
		int k;
		int flag=0;			// impossible的情况(当且仅当说I am lying.才是此情况)
		int kind=sb.size();		//出现的种类数(最后要输出的种类数)
		int possible_way=0;		//合法的身份方案,  如果仅有一种,则输出,否则表示都多种情况 
		int all=(int)pow(3.0,5);	//枚举范围0-all
		string ans[6];				//用来保存 找到合法的身份方案后 的那5个身份 
		int has_change[6];			//用来记录 找到的多个合法方案中 某人的身份是否一样 (如果一样,表示某个人的身份在什么时候都是确定的,反之则否)
		memset(has_change,0,sizeof(has_change));
		int ans_d_n=-1;	//用来保存 找到合法的身份方案后 的时间,如果一直不变,表示这个时间也是固定的,同has_change数组的理
		int has_changed_d_n=0;	//记录 合法方案的时间是否改变,理由同上
		int line=1;			//标志 当前方案是否第一次出现,
		int day_night;		//时间变量,1为白天,0为黑夜
		int twice=0;		//枚举 每种方案 在白天 和 黑夜下的情况
		for (k=0;k<all;k++)
		{
			
			if (twice==1)//第二次 把时间看作黑夜,并且k--回到上个方案
			{
				twice++;
				k--;
				day_night=0;
				continue;
			}
			
			if (twice==0)//第一次 把时间看作白天
			{
				twice++;
				day_night=1;
			} 
			if (twice==2)		//复位
				twice=0;
			
			int tmp=k; 
			
			for (i=1;i<=5;i++)		//枚举身份
			{
				
				if (tmp%3==0) 
					what[i]="divine";
				else
					if (tmp%3==1) what[i]="human";
					else
						what[i]="evil";
					tmp=tmp/3;
			}
			
			int find_ans=1;		//是否找到一个合法方案
			for (i=1;i<=n;i++)
			{
				if (tm[i].d_or_n!=-1)	//如果第i句话与时间相关
				{
					
					if (day_night==tm[i].d_or_n)  //如果第i句话时间与当前方案时间相同,即本句话为真 
					{
						if (what[tm[i].spker-'A'+1]=="divine") //神族说真话,没问题
							continue;
						if (what[tm[i].spker-'A'+1]=="evil")  //恶魔说真话,本方案不合法,结束
						{find_ans=0;break;}
						if (what[tm[i].spker-'A'+1]=="human")	//人
						{
							if (day_night==1) continue;		//白天说真话,ok
							else 	{find_ans=0;break;}		//晚上说真话,本方案不合法,结束
						} 
					}
					else	 //如果第i句话时间与当前方案时间相同,即本句话为假 ,下面的具体就不分析了
					{
						if (what[tm[i].spker-'A'+1]=="divine")	
						{find_ans=0;break;}
						if (what[tm[i].spker-'A'+1]=="evil")
							continue;
						if (what[tm[i].spker-'A'+1]=="human")
						{
							if (day_night==1) {find_ans=0;break;}
							else 	continue;
						} 
					}
				}
				//下面的都是本句话与时间 无关的情况
				
				if (tm[i].what=="lying")		//谁谁谁 lying 的情况
				{
					if (tm[i].is_not==1)		//如果说 某人【在】说谎
					{
						if (tm[i].spker==tm[i].who)  //如果自己说自己说谎, 这是唯一的 不可能的方案,flag标记,结束所有方案,输出答案
						{flag=1;	find_ans=1;break;}
						
						int isreal;						//其余情况要先判断 这句话是否为真 (先不考虑说话人,只考虑说的话)
						if (what[tm[i].who-'A'+1]=="divine")	 //神不可能撒谎,本句话为假
							isreal=0;
						if (what[tm[i].who-'A'+1]=="human")		//人类撒谎根据时间
						{ 
							if (day_night==1)	isreal=0;
							else isreal=1;
						} 
						if (what[tm[i].who-'A'+1]=="evil")		//恶魔撒谎
							isreal=1;
						
						if (isreal)  	//如果 shuo 的是真话
						{
							if (what[tm[i].spker-'A'+1]=="divine")	//神说真话,合法
								continue; 
							if (what[tm[i].spker-'A'+1]=="human")	//人是否合法得看时间
							{ 
								if (day_night==0)
								{ find_ans=0;break; }
							}
							if (what[tm[i].spker-'A'+1]=="evil")	//恶魔不说真话
							{ find_ans=0;break; } 
						}
						else	//说的是假话
						{
							if (what[tm[i].spker-'A'+1]=="divine")
							{find_ans=0;break;} //矛盾
							if (what[tm[i].spker-'A'+1]=="human")
							{
								if (day_night==1)	{find_ans=0;break;} //本应该说真话却说假话
								else if (day_night==0) continue; //晚上说假话 
							}
							if (what[tm[i].spker-'A'+1]=="evil")
								continue; 
						}
					}	
					else		//	//如果说 某人【不在】说谎
					{
						int isreal;								//依旧先判断 话的真假
						if (what[tm[i].who-'A'+1]=="divine")
							isreal=1;
						if (what[tm[i].who-'A'+1]=="human")
						{ 
							if (day_night==1)	isreal=1;
							else isreal=0;
						} 
						if (what[tm[i].who-'A'+1]=="evil")
							isreal=0;
						
						
						if (isreal)	//如果 shuo 的是真话
						{
							if (what[tm[i].spker-'A'+1]=="divine")
								continue; 
							if (what[tm[i].spker-'A'+1]=="human")
							{ 
								if (day_night==0)
								{ find_ans=0;break; }
							}
							if (what[tm[i].spker-'A'+1]=="evil")
							{ find_ans=0;break; }
						}
						else		//如果说的是假话
						{
							if (what[tm[i].spker-'A'+1]=="divine")
							{find_ans=0;break;} //矛盾
							if (what[tm[i].spker-'A'+1]=="human")
							{
								if (day_night==1)	{find_ans=0;break;} //本应该说真话却说假话
								else if (day_night==0) continue; //晚上说假话 
							}
							if (what[tm[i].spker-'A'+1]=="evil")
								continue;
							
						}
					}
				}
				else  	//下面的情况 就是 xxx是什么身份 这种句式
				{
					if (tm[i].is_not==1)     //如果是肯定句
					{
						if (tm[i].what==what[tm[i].who-'A'+1])//与被描述者身份一致,本句为真话  
						{
							if (what[tm[i].spker-'A'+1]=="divine")
								continue;
							if (what[tm[i].spker-'A'+1]=="human")
							{
								if (day_night==1) continue;  //本应该说真话却说假话
								else if (day_night==0) 	{find_ans=0;break;} //晚上说假话 
							}
							if (what[tm[i].spker-'A'+1]=="evil")
							{find_ans=0;break;}
						}
						else //与被描述者身份不一致,本句为假话  
						{
							if (what[tm[i].spker-'A'+1]=="divine")
							{find_ans=0;break;} //矛盾
							if (what[tm[i].spker-'A'+1]=="human")
							{
								if (day_night==1)	{find_ans=0;break;} //本应该说真话却说假话
								else if (day_night==0) continue; //晚上说假话 
							}
							if (what[tm[i].spker-'A'+1]=="evil")
								continue;
						}
					}
					else			//如果整句话是否定句 
					{
						if (tm[i].what==what[tm[i].who-'A'+1])   //与被描述者身份一致,本句为假话  
						{
							if (what[tm[i].spker-'A'+1]=="divine")
							{find_ans=0;break;} //矛盾
							if (what[tm[i].spker-'A'+1]=="human")
							{
								if (day_night==1) 	{find_ans=0;break;}  //本应该说真话却说假话
								else if (day_night==0) continue; //晚上说假话 
							}
							if (what[tm[i].spker-'A'+1]=="evil")
								continue;
						}
						else					//与被描述者身份不一致,本句为真话  
						{
							if (what[tm[i].spker-'A'+1]=="divine")
								continue;
							if (what[tm[i].spker-'A'+1]=="human")
							{
								if (day_night==1) continue;  //本应该说真话却说假话
								else if (day_night==0) 	{find_ans=0;break;}//晚上说假话 
							}
							if (what[tm[i].spker-'A'+1]=="evil")
							{find_ans=0;break;}
						}
					}
				}
			}
			
			if (flag)		//impossible的情况
				break; 
			if (find_ans)		//找到一种合法方案
			{	 
				int h;
				for (h=1;h<=5;h++)		//储存答案
				{ 
					if (line)		//如果是第一次找到合法方案,直接存下来,并在后面去掉首次标记
					{
						ans[h]=what[h];continue;   
					}
					if (ans[h]!=what[h])		//非第一次找到答案,先比较当前答案与以前的是否一致
					{
						ans[h]=what[h];			//更新答案并且
						has_change[h]=1;		//如果不一致,标志这个人的身份是不确定的
					}
				}
				if (ans_d_n!=day_night&&!line)	//更新时间,并看是否一直不变
					has_changed_d_n=1;
				ans_d_n=day_night;		//储存时间
				possible_way++;			//方案数++ 
				line=0;
			}	
	}
	
	
	if (possible_way==0||flag)   //无合法方案,或者遇到flag情况
		printf("This is impossible.\n");
	else
		if (possible_way>1)		//方案有很多
		{
			int has=0;		//记录是否有输出过答案
			it=sb.begin();		//遍历出现过的人
			for (int h=1;h<=kind;h++,it++)	
			{
				int p= (*it)-'A'+1;		//出现过的人的编号
				if (has_change[p]==0)		//如果在多个方案中 身份都一样,则标明身份确定,输出,并更新标记
				{
					printf("%c is %s.\n",p-1+'A',ans[p].c_str());
					has=1;							//表示输出过答案
				}
			}
			
			if (has_changed_d_n==0)		//如果时间在多个方案中不曾改变
				if (ans_d_n!=-1)		
					printf("It is %s.\n",(ans_d_n==1)?"day":"night"),has=1;		//输出答案并更新标记
				
				if (!has)			//如果 人的身份或时间都不是确定的,输出 无法确定事实
					printf("No facts are deducible.\n");
		}
		else		//如果方案只有一种。。。。必然就是合法的唯一的方案
		{
			it=sb.begin();
			
			for (i=1;i<=kind;i++,it++)
			{
				int p= (*it)-'A'+1;
				printf("%c is %s.\n",p-1+'A',ans[p].c_str());
			}
			if (ans_d_n!=-1)							
				printf("It is %s.\n",(ans_d_n==1)?"day":"night");
			
		} 
		printf("\n");		
		}  
		
		
		return 0;
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator