1. 程式人生 > 其它 >洛谷 P7541 DOBRA 題解

洛谷 P7541 DOBRA 題解

hhh... 我又來寫題解了

solution

題意簡化

一個字串,將所有的 _ 替換成大寫字母,使結果字串符合要求:

1、不包含三個連續 母音 或 子音 字母;

2、字串中至少有一個 L

求最終字串可能的個數。


看到這道題,即想到了萬能的演算法——搜尋。

從下標 \(0\) 開始,列舉每一個字母。

由於每次列舉的字母與後面的列舉無關,所以這樣搜尋不會出現重複的終串。

在列舉結束時使用 check 檢測是不是合法終串,如果是就是一種情況。

注意:char 陣列不會克隆,需要回溯。

#include#include<bits/stdc++.h>
using namespace std;
int yy[127];

int check(char ns[])
{
	bool flag=0;

	for(int i=0,len=strlen(ns);i<len-2;i++)
	{
		if((yy[ns[i]]==1&&yy[ns[i+1]]==1&&yy[ns[i+2]]==1)
           ||
          ((!yy[ns[i]])&&(!yy[ns[i+1]])&&(!yy[ns[i+2]]))) return -1;
        
		if(!flag&&(ns[i]=='L'||ns[i+1]=='L'||ns[i+2]=='L')) flag=true;
	}
	return flag;
}

long long dfs(int i,char ns[])
{
	if(i==strlen(ns)) return max(check(ns),0);
	if(check(ns)==-1) return 0;
	if(ns[i]!='_') return dfs(i+1,ns); //這裡可優化 ;;雖然對結果沒啥影響

	long long ans=0;
	for(char ch='A';ch<='Z';ch++)
	{
		ns[i]=ch;
		ans+=dfs(i+1,ns);
	}
	ns[i]='_';
	return ans;
}

int main()
{
	//init
	yy['A']=yy['E']=yy['I']=yy['O']=yy['U']=1;
	yy['_']=-1;

	char chr[1001];
	scanf("%s",chr);
	cout<<dfs(0,chr);
	return 0;
}1

可惜,只會拿到可憐的 \(30\%\) 的分數。

先來算算時間複雜度吧。

對於每次操作,都有每個 _ 需要列舉 \(26\) 次,保證最多有 \(10\) 個,所以列舉次數最少 \(10^{26}\) 次方,超時是穩穩的。

所以如何減少時間複雜度呢?

我們可以發現,這道題實際上子音字母之間並沒有區別。同理,對於母音字母也是如此。

所以,可以每次只列舉兩次,對於子音字母的結果乘 \(26-5=21\);母音字母的結果乘 \(5\)

還有一點要注意,由於 L 會影響結果,所以需要特殊考慮。

總共 \(3\) 次,列舉次數降為 \(10^3\) ,AC 穩穩的。

AC Code:

#include<bits/stdc++.h>
using namespace std;
int yy[127];

int check(char ns[])
{
	bool flag=0;

	for(int i=0,len=strlen(ns);i<len-2;i++)
	{
		if((yy[ns[i]]==1&&yy[ns[i+1]]==1&&yy[ns[i+2]]==1)
           ||
          ((!yy[ns[i]])&&(!yy[ns[i+1]])&&(!yy[ns[i+2]]))) return -1;
        
		if(!flag&&(ns[i]=='L'||ns[i+1]=='L'||ns[i+2]=='L')) flag=true;
	}
	return flag;
}

long long dfs(int i,char ns[])
{
	int len=strlen(ns);
	while(ns[i]!='_'&&i<len) i++;   //可優化遞迴層數,可惜只有100,沒啥用
	if(i==len) return max(check(ns),0);
	if(check(ns)==-1) return 0;

	long long ans=0;
	ns[i]='A';  //這裡泛指母音字母
	ans+=dfs(i+1,ns)*5;
	ns[i]='B';  //這裡泛指子音字母
	ans+=dfs(i+1,ns)*20;  //將 L 特殊考慮,21-1 即為 20
	ns[i]='L';
	ans+=dfs(i+1,ns);
	ns[i]='_';
	return ans;
}

int main()
{
	//init
	yy['A']=yy['E']=yy['I']=yy['O']=yy['U']=1;
	yy['_']=-1;


	char chr[1001];
	scanf("%s",chr);
	cout<<dfs(0,chr);
	return 0;
}

從 9 s 降到 30ms,質的提升啊!


求過!