您的位置:首页 > 其它

Codeforces Round #288 (Div. 2) E. Arthur and Brackets [dp 贪心]

2015-01-29 15:42 489 查看
E. Arthur and Brackets

time limit per test
2 seconds

memory limit per test
128 megabytes

input
standard input

output
standard output

Notice that the memory limit is non-standard.

Recently Arthur and Sasha have studied correct bracket sequences. Arthur understood this topic perfectly and become so amazed about correct bracket sequences, so he even got himself a favorite correct bracket sequence of length 2n. Unlike Arthur, Sasha understood the topic very badly, and broke Arthur's favorite correct bracket sequence just to spite him.

All Arthur remembers about his favorite sequence is for each opening parenthesis ('(') the approximate distance to the corresponding closing one (')'). For the i-th opening bracket he remembers the segment [li, ri], containing the distance to the corresponding closing bracket.

Formally speaking, for the i-th opening bracket (in order from left to right) we know that the difference of its position and the position of the corresponding closing bracket belongs to the segment [li, ri].

Help Arthur restore his favorite correct bracket sequence!

Input
The first line contains integer n (1 ≤ n ≤ 600), the number of opening brackets in Arthur's favorite correct bracket sequence.

Next n lines contain numbers li and ri (1 ≤ li ≤ ri < 2n), representing the segment where lies the distance from the i-th opening bracket and the corresponding closing one.

The descriptions of the segments are given in the order in which the opening brackets occur in Arthur's favorite sequence if we list them from left to right.

Output
If it is possible to restore the correct bracket sequence by the given data, print any possible choice.

If Arthur got something wrong, and there are no sequences corresponding to the given information, print a single line "IMPOSSIBLE" (without the quotes).

Sample test(s)

Input
4
1 1
1 1
1 1
1 1


Output
()()()()


Input
3
5 5
3 3
1 1


Output
((()))


Input
3
5 5
3 3
2 2


Output
IMPOSSIBLE


Input
3
2 3
1 4
1 4


Output
(())()


一把一把的泪啊,,,看错题搞了很久,,,然后dp时输出串也搞了很久,,,原来水水的贪心就能过,,,泪流满面,

转一下贪心的思路: http://www.cnblogs.com/wuyuewoniu/p/4256013.html
CF上给这道题打了dp和greedy两个标签,应该是两种做法都可以吧。下面说贪心的做法。

题意:

有一些配好对的括号,现在已知第i对括号,左右括号的距离在[Li, Ri]区间中。按照左括号出现的顺序编号。

输出原括号序列。

分析:

因为括号是以栈的形式配对的,所以我们将这些区间也以栈的形式存储。

假设第i对括号的左括号在位置p,则右括号只能在[p+Li, p+Ri]这个区间中。

每放一个左括号,就将右括号对应的区间入栈。

贪心的办法是,如果当前位置位于栈顶区间的范围内,则尽早入栈。

贪心的理由是:因为早点使栈顶的括号配对,就有更大的机会使栈顶的第二队括号配上对。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<string>

#define N 1205
#define M 105
#define mod 1000000007
//#define p 10000007
#define mod2 1000000000
#define ll long long
#define LL long long
#define eps 1e-6
#define inf 100000000
#define maxi(a,b) (a)>(b)? (a) : (b)
#define mini(a,b) (a)<(b)? (a) : (b)

using namespace std;

int n;
char s
;
int l
,r
;
int flag;
int dp[605][605];

void ini()
{
memset(dp,-1,sizeof(dp));
int i;
for(i=1;i<=n;i++){
scanf("%d%d",&l[i],&r[i]);
}
flag=0;
s[2*n]='\0';
}

int fun(int now,int tot,int st,int en)
{
// printf("now=%d tot=%d st=%d en=%d\n",now,tot,st,en);
int f1,f2;
int i;
int tot1,tot2;
int ss,ee;
if(dp[now][tot]!=-1){
return dp[now][tot];
}
if(tot==1){
if(l[now]==1){
dp[now][tot]=1;
return 1;
}
else{
dp[now][tot]=0;
return 0;
}
}
ss=l[now];ee=r[now];
if(ss%2==0) ss++;
if(ee%2==0) ee--;
for(i=ss;i<=min(ee,en-st);i+=2){
tot1=(i+1)/2;
tot2=tot-tot1;
//printf(" i=%d tot1=%d tot2=%d\n",i,tot1,tot2);
if(tot2<0) break;
if(tot1==1){
f2=fun(now+1,tot2,st+2,en);
if(f2>=1){
dp[now][tot]=1;
return 1;
}
}
else if(tot1==tot){
f1=fun(now+1,tot1-1,st+1,en-1);
if(f1>=1){
dp[now][tot]=i;
return 1;
}
}
else{
f1=fun(now+1,tot1-1,st+1,st+i-1);
f2=fun(now+tot1,tot2,st+i+1,en);
if(f1>=1 && f2>=1){
dp[now][tot]=i;
return 1;
}
}
}
dp[now][tot]=0;
return 0;
}

void solve()
{
flag=fun(1,n,1,2*n);
}

void print(int now,int tot)
{
int tot1,tot2;
tot1=(dp[now][tot]+1)/2;
tot2=tot-tot1;
printf("(");
if(tot1!=1)
print(now+1,tot1-1);
printf(")");
if(tot1!=tot)
print(now+tot1,tot2);

}

void out()
{
/* int i,j;
printf("flag=%d\n",flag);
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
printf(" i=%d j=%d dp=%d\n",i,j,dp[i][j]);
}
}*/
if(flag==0){
printf("IMPOSSIBLE\n");
}
else{
print(1,n);
printf("\n");
//printf("%s\n",s);
}
}

int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
//scanf("%d",&T);
//for(int ccnt=1;ccnt<=T;ccnt++)
//while(T--)
while(scanf("%d",&n)!=EOF)
{
ini();
solve();
out();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: