题解 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 排序,在过程中就无需考虑字典序。于是就写完了……

code:

#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

欢迎交流讨论,请点个赞哦~

posted @ 2021-06-25 22:11  Maplisky  阅读(89)  评论(0编辑  收藏  举报