啊哈今日份TC
题目描述
有n个人围成一个圈,按照逆时针方向标号为0到n-1。这些人中有一些撒谎者。现在,你想知道最少有多少个人撒谎,于是你问了一些人他逆时针方向的人有没有撒谎。字符串answers描述了你所得到的答案:
- answers[i]=’L’ 表示第i个人说第(i+1)个人撒谎了
- answers[i]=’H’ 表示第i个人说第(i+1)个人没有撒谎
- answers[i]=’?’ 表示你没有询问第i个人
如果至少能找到一种方案使得answers是合法的,输出最少的撒谎人数。否则输出-1
样例
Input1
LLH
Output1
1
根据输入:
- 0说1撒谎了。
- 1说2撒谎了。
- 2说0没有撒谎。
显然,他们不可能都是诚实的,所以至少有一个人撒谎了。 可能1撒谎了而另外两个人没有。 因此,最少的撒谎人数就是一个。 (也有可能1没有撒谎,另外两人撒谎了,但是这种方案撒谎人数不是最小)
Input2
?????
Output2
0
Input3
LHLH?
Output3
2
Input4
??LLLLLL??
Output4
3
Input5
LLL
Output5
-1
根据输入:
- 0说1撒谎了。
- 1说2撒谎了。
- 2说0撒谎了。
那么
- 假设0撒谎了:1就没有撒谎,2撒谎了,那么根据2的回答,0没有撒谎,和假设矛盾
- 假设0没撒谎:1撒谎了,2没有撒谎,那么根据2的回答,0撒谎了,和假设矛盾
所以没有合法的方案
分析
根据样例,我们可以发现,如果answers中没有’?’,我们可以通过0一个人的情况得出所有人有没有撒谎,最后通过n-1的回答判断这种方案是不是合法,最终得出答案。那么关键是处理’?’的情况。
假设answer[x]=’?’——
最先想到的就是暴力枚举两种情况——x+1撒谎了或者没有撒谎,但是如果字符串长度为50,每一个位上都是’?’,那么不剪枝大概是会T掉的,所以我们可以进行优化:
如果answers[x+1]也是’?’,那么x+1的情况就不会受限制,为了让答案尽量小,我们肯定默认x+1没有说谎,所以就不用判断说谎的情况了,这样大概就会优秀一点了
代码
既丑陋又充满废话的代码
//tc is healthy, just do it
#include <bits/stdc++.h>
const int N=55;
using namespace std;
template<class T> void checkmin(T &a,const T &b) { if (b<a) a=b; }
template<class T> void checkmax(T &a,const T &b) { if (b>a) a=b; }
class ConundrumReloaded {
public:
int minimumLiars( string answers ) ;
};
int n,a[N],b[N],ans,tot=0;
string answers;
void search(int pos,int lie,int num){//表示前pos个人的撒谎情况已知,第pos个
//人是否撒谎,目前一共有num个人撒谎
if(num>=ans)return;
if(pos==n+1){
if(lie==b[1]||lie==3){
ans=min(ans,num);
}
return;
}
if(a[pos]!=3){
if(lie==1){
int yh=0;
if(a[pos]==2&&pos!=n)yh=1;//注意要判断pos!=n,否则就会多算一个撒谎人数
search(pos+1,3-a[pos],num+yh);
}
else{
int yh=0;
if(a[pos]==1&&pos!=n)yh=1;
search(pos+1,a[pos],num+yh);
}
}
else {
if(a[pos+1]==3){
search(pos+1,2,num);
return;
}
search(pos+1,2,num);
if(pos!=n)search(pos+1,1,num+1);
else search(pos+1,1,num);
}
}
int ConundrumReloaded::minimumLiars(string answers) {
n=answers.length();
ans=n+1;
for(int i=1;i<=n;i++){
if(answers[i-1]=='L')a[i]=1;
if(answers[i-1]=='H')a[i]=2;
if(answers[i-1]=='?')a[i]=3;
}
b[1]=1;
search(1,1,1);
b[1]=2;
search(1,2,0);
if(ans==n+1)ans=-1;
return ans;
}