題目分析
這道題表面上看上去挺簡單,其實仔細研究一下還是值得鑽研的。我本人做這道題使用的任然是$ DFS01 $揹包。不過呢,與往常揹包不同的是,這次遞迴中需要加許多引數。就資料強度來看,棧問題不大。
遞迴過程
我們使用一個棧以及兩個臨時棧。每次在裡面$ push $當前的解。只有“G”與“B”。兩個棧分別處理和紅茶和和綠茶的情況。兩種情況都要考慮到已經連續喝了幾次某種茶。
在遞迴函式裡,我們用到$ dep,s,g,h,last $ 這幾個變數。分別代表深度、連續喝的總數、綠茶喝的總數、紅茶喝的總數以及上次喝的茶是啥。$ 0 $代表綠茶,\(1\)代表紅茶。
遞迴程式碼:
void dfs(int dep,int s,int g,int h,bool last)
{
if(dep>n)
{
stack<string>temp1=temp;
while(!temp1.empty())
{
cout<<temp1.top();
temp1.pop();
}
exit(0);
}
else
{
if(last==0)
{
temp.push("G");
if(g+1<=a)dfs(dep+1,s,g+1,h,!last);
if(s+1<=b&&s<k) dfs(dep+1,s+1,g,h+1,last);
else
{
cout<<"NO"<<endl;
exit(0);
}
}
else
{
temp.push("B");
if(s+1<=b)dfs(dep+1,s,g,h+1,!last);
if(g+1<=a&&s<k) dfs(dep+1,s+1,g,h,last);
else
{
cout<<"NO"<<endl;
exit(0);
}
}
if(!temp.empty()) temp.pop();
}
主函式
最後主函式的程式就簡單了。像往常一樣,$ dep \(總是要是\) 1 \(開始,其他都是\) 0 $;但是有一個問題,我們不僅要考慮第一次喝綠茶的情況,第一次還可能是紅茶。所以我們在剛開始寫遞迴函式的時候,我們需要遞迴兩遍
主函式程式碼:
int main()
{
cin>>n>>k>>a>>b;
dfs(1,0,0,0,0);
dfs(1,0,0,0,1);
return 0;
}
完整程式碼
#include<bits/stdc++.h>
using namespace std;
int n,k,a,b;
stack<string>temp;
void dfs(int dep,int s,int g,int h,bool last)
{
if(dep>n)
{
stack<string>temp1=temp;
while(!temp1.empty())
{
cout<<temp1.top();
temp1.pop();
}
exit(0);
}
else
{
if(last==0)
{
temp.push("G");
if(g+1<=a)dfs(dep+1,s,g+1,h,!last);
if(s+1<=b&&s<k) dfs(dep+1,s+1,g,h+1,last);
else
{
cout<<"NO"<<endl;
exit(0);
}
}
else
{
temp.push("B");
if(s+1<=b)dfs(dep+1,s,g,h+1,!last);
if(g+1<=a&&s<k) dfs(dep+1,s+1,g,h,last);
else
{
cout<<"NO"<<endl;
exit(0);
}
}
if(!temp.empty()) temp.pop();
}
int main()
{
cin>>n>>k>>a>>b;
dfs(1,0,0,0,0);
dfs(1,0,0,0,1);
return 0;
}