POJ 1068 Parencodings

题目描述:
给出一个括号序列,规定一下两种编码形式:
1)P-sequence:P = p1 p2 ... pn,其中pi表示第i个右括号左边的左括号个数;
2)
W-sequence:W = w1 w2 ... wn,其中wi表示在第i个右括号和与之相匹配的左括号之间的右括号个数(包括第i个右括号)
示例如下:
括号序列S:           (  (  (  (  )  (  )  (  )  )  )  )         //相匹配的括号用相同颜色标出
对应的P-sequence:             4    5 6 6 6 6
对应的W-sequence:            1    1 1 4 5 6 
给出一个序列的P-sequence,要求输出对应的W-sequence

算法描述:
1)将输入的P-sequence转换成对应的括号序列S;
2)根据序列S转换出对应的W-sequence并输出;
把由P-sequence转换出的括号序列左括号用-1表示,右括号用1表示,然后遍历整个序列,遇到1(右括号)则从当前位置往前搜索,寻找与之匹配的-1(左括号),匹配过程中把每一对匹配后的括号分别标记为-2(匹配后的左括号)和2(匹配后的右括号),这样直接统计每次匹配过程中经过的值为2的元素数量即可得到W-sequence每一位的数值。

例如:
P-sequence: 4 5 6 6 6 6
转换成括号序列S:(  (  (  (  )  (  )  (  )  )  )  
把上面的括号序列编码:-1 -1 -1 -1 1 -1 1 -1 1 1 1 1
匹配过程如下:
1)遍历到第一个 1(右括号),向前寻找最近的未匹配过的左括号(-1),并将匹配到的1置为2,-1置为-2,得到第一次匹配后的序列为:-1 -1 -1 -2 2 -1 1 -1 1 1 1 1,该过程中右括号数 w1 = 1;
2)按照1)的方法,第二次匹配后的序列:-1 -1 -1 -2 2 -2 2 -1 1 1 1 1, w2 = 1;
3)                   第三次匹配后的序列:-1 -1 -1 -2 2 -2 2 -2 2 1 1 1, w3 = 1;
4)                   第四次匹配后的序列:-1 -1 -2 -2 2 -2 2 -2 2 2 1 1, w4 = 4;

5)                   第五次匹配后的序列:-1 -2 -2 -2 2 -2 2 -2 2 2 2 1, w5 = 5;

6)                   第五次匹配后的序列:-2 -2 -2 -2 2 -2 2 -2 2 2 2 2, w6 = 6; 


Code:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 100;
int main()
{
    int t, n;
    int indx[maxn];
    int numvis[maxn];
    scanf( "%d", &t );
    for( int i = 0; i < t; i++ )
    {
        scanf( "%d", &n );
        for( int j = 1; j <= n; j++ )
            scanf( "%d", &indx[j] );
        indx[0] = 0;
        int co = 1;
        for( int j = 1; j <= n; j++ )
        {//把输入的 P-sequence 转换成对应的左右括号序列,左括号用-1表示,右括号用1表示
            if( indx[j] - indx[j-1] == 0 )
            {
                numvis[co++] = 1;
            }
            else
            {
                for( int k = 0; k < indx[j] - indx[j-1]; k++ )
                {
                    numvis[co++] = -1;
                }
                numvis[co++] = 1;
            }
        }
        bool blank = 0;
        for( int j = 1; j < co; j++ )
        {
            if( numvis[j] == 1 )
            {//遍历转换后的序列,遇到右括号寻找与之匹配的左括号并按题目要求计数,并对匹配完的括号做标记
                int ans = 1;
                for( int k = j-1; k >= 1; k-- )
                {
                    if( numvis[k] == -1 )
                    {
                        numvis[k] = -2;
                        numvis[j] = 2;
                        break;
                    }
                    else
                    {
                        k -= 1;
                        ans++;
                    }
                }
                if( !blank )
                {
                    printf( "%d", ans );
                    blank = 1;
                }
                else
                    printf( " %d", ans );
            }
        }
        printf( "\n" );
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值