1. 程式人生 > 其它 >題解 P6439 [COCI2011-2012#6] ZAGRADE

題解 P6439 [COCI2011-2012#6] ZAGRADE

題目傳送門

更好的閱讀體驗

演算法分析:記憶化搜尋

一道水題。

首先利用棧進行括號匹配,遇到左括號入棧,遇到右括號則把棧頂彈出並記錄。不多說,程式碼如下:

inline void cot() {
	stack<int> s;
	F(i,1,n) {
		if(c[i]=='(')s.push(i);
		if(c[i]==')')b[++cnt]= {s.top(),i},s.pop();
	}
}

然後就是搜尋,由於括號數量較少,可以用狀壓記錄使用情況。對於每一種狀態,暴力統計消去的括號的位置,然後再暴力將剩餘的字元加到一個字串中。用 string 儲存,最終可以直接 sort 排序,在過程中就無需考慮字典序。於是就寫完了……

程式碼如下:

#include<bits/stdc++.h>
#define reg register
#define F(i,a,b) for(reg int i=a;i<=b;++i)
using namespace std;
const int N=1e4+10,M=250;
int n,cnt,now;
bool vis[M],meet[N];
char c[M];
struct P {
	int l,r;
} b[N];
string s[N];
inline void cot() {//括號匹配 
	stack<int> s;
	F(i,1,n) {
		if(c[i]=='(')s.push(i);
		if(c[i]==')')b[++cnt]= {s.top(),i},s.pop();
	}
}
inline void inp(int sta) {//暴力組合字元 
	++now;
	F(i,1,cnt) {
		int l=b[i].l,r=b[i].r;
		if(sta&(1<<i-1))vis[l]=vis[r]=1;
	}
	F(i,1,n){
		if(!vis[i])s[now]+=c[i];
		vis[i]=0;
	}
}
void dfs(int sta) {

	if(meet[sta])return;
	meet[sta]=1;//記憶化 

	if(sta)inp(sta);//記錄當前狀態下的字串 
	F(i,1,cnt) {//搜尋 
		if(sta&(1<<i-1))continue;
		dfs(sta|(1<<i-1));
	}
}
int main() {
	getline(cin,s[0]);
	n=s[0].size();
	F(i,0,n-1)if(s[0][i]!=' ')c[i+1]=s[0][i];
	cot();
	dfs(0);
	sort(s+1,s+now+1);//排序 
	now=unique(s+1,s+now+1)-s-1;//去重 
	F(i,1,now)cout<<s[i]<<endl;
	return 0;
}

AC

歡迎交流討論,請點個贊哦~