[題解]TopCoder SRM 625 div2 T3 ConundrumReloaded
阿新 • • 發佈:2018-11-06
啊哈今日份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;
}