PAT A 1148 AC代码(两种可行思路和代码)

应该是20分题里面容易出问题的题目了。


思路一(可行但是复杂,不推荐,推荐下面的思路二):

(可以帮助这个思路写但是测试点3不过的同学,因为现实中解这种问题可能更多先想到这思路)

拿到题目我的第一思路是:分别假设两个人撒谎,反转撒谎人的话,然后根据他们的话去确定身份,再在不违背已知身份的条件下,假设说谎人身份一狼一好,然后统计符合狼数条件的情况。

!!!要注意的问题:根据所有人的话,再加上你不违背话的假设,无法确定每个人的身份,有的人是好人,有的人是狼人,还有部分是无法确定的身份,这个时候会出现两种可能满足的情况:

1、遍历后发现,有两只狼,满足所有条件,将狼号存入ans

2、遍历后发现,有一只狼,且有无法确定身份之人,可以满足条件,将狼号和第一个不确定身份的人的号码(因为输出条件中只要号码小的,只需要存该情况下,最小的可能狼)存入ans(存的时候用一下,max和min保证一下大小顺序)

AC代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int N;
struct node{
	int a,b;
};
vector<int> v;
vector<node> ans;
bool cmp(const node x1,const node x2){
	if(x1.a==x2.a){
		return x1.b<x2.b;
	}else{
		return x1.a<x2.a;
	}
}
int main(){
	cin>>N;
	v.resize(N+1);
	for(int i=1;i<=N;i++){
		scanf("%d",&v[i]);
	}
	for(int i=1;i<N;i++){
		for(int j=i+1;j<=N;j++){ //假设i和j说谎
			int tag[N+1]={0};
			bool flag1=true;
			vector<int> test=v;
			test[i]*=-1;          //反转话语
			test[j]*=-1;
			for(int m=1;m<=N;m++){
				if(test[m]>0){
					if(tag[test[m]]==-1){ //排除矛盾
						flag1=false;
						break;
					}
					tag[test[m]]=1;
				}else{
					if(tag[abs(test[m])]==1){ //排除矛盾
						flag1=false;
						break;
					}
					tag[abs(test[m])]=-1;
				}
			}
			if(flag1){
				vector<int> temp,temp0;
				int ct=0;
				if(tag[i]!=-1&&tag[j]!=1){ //假设i好,j狼
					tag[i]=1;
					tag[j]=-1;
					for(int m=1;m<=N;m++){
						if(tag[m]==-1){ //存狼
							ct++;
							temp.push_back(m);
						}
						if(tag[m]==0){  //存身份不确定的人
							temp0.push_back(m);
						}
					}
					if(ct==1&&temp0.size()!=0){ //一狼且有不确定的人
						ans.push_back(node{min(temp[0],temp0[0]),max(temp[0],temp0[0])});
					}
					if(ct==2){ //恰好两狼
						ans.push_back(node{temp[0],temp[1]});
					}
				}
				if(tag[i]!=1&&tag[j]!=-1){ //假设i狼,j好
					tag[i]=-1;
					tag[j]=1;
					ct=0;
					temp.clear();
                    temp0.clear();
					for(int m=1;m<=N;m++){
						if(tag[m]==-1){
							ct++;
							temp.push_back(m);
						}
						if(tag[m]==0){
							temp0.push_back(m);
						}
					}
					if(ct==1&&temp0.size()!=0){ //一狼且有不确定的人
						ans.push_back(node{min(temp[0],temp0[0]),max(temp[0],temp0[0])});
					}
					if(ct==2){ //恰好两狼
						ans.push_back(node{temp[0],temp[1]});
					}
				}
			}
		}
	}
	sort(ans.begin(),ans.end(),cmp);
	if(ans.size()==0){
		printf("No Solution\n");
	}else{
		printf("%d %d\n",ans[0].a,ans[0].b);
	}
	return 0;
}

思路二(推荐,参考了柳神的思路,秒,膜)

直接假设两狼,其他是好,然判断其余条件:

1、是否恰好两人说谎

2、说谎人一好一狼

满足则将此情况统计

AC代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int N;
vector<int> v;
struct node{
	int a,b;
};
bool cmp(const node x1,const node x2){
	if(x1.a==x2.a){
		return x1.b<x2.b;
	}else{
		return x1.a<x2.a;
	}
}
int main(){
	cin>>N;
	v.resize(N+1);
	vector<node> ans;
	for(int i=1;i<=N;i++){
		scanf("%d",&v[i]);
	}
	for(int i=1;i<N;i++){
		for(int j=i+1;j<=N;j++){
			vector<int> tag(N+1,1);
			vector<int> liar;
			tag[i]=-1;
			tag[j]=-1;
			for(int m=1;m<=N;m++){
				if(v[m]*tag[abs(v[m])]<0){
					liar.push_back(m);
				}
			}
			if(liar.size()==2&&(tag[liar[0]]*tag[liar[1]]==-1)){
				ans.push_back(node{i,j});
			}
		}
	}
	sort(ans.begin(),ans.end(),cmp);
	if(ans.size()==0){
		printf("No Solution\n");
	}else{
		printf("%d %d\n",ans[0].a,ans[0].b);
	}
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值