uva1423(拓扑排序)

Given a sequence of integers, a1, a2, … , an, we define its sign matrix S such that, for 1 ≤ i ≤ j ≤ n,
Sij = “ + ” if ai + … + aj > 0; Sij = “ − ” if ai + … + aj < 0; and Sij = “0” otherwise.
For example, if (a1, a2, a3, a4) = (−1, 5, −4, 2), then its sign matrix S is a 4 × 4 matrix:
1 2 3 4
1 − + 0 +
2 + + +
3 − −
4 +
We say that the sequence (−1, 5, −4, 2) generates the sign matrix. A sign matrix is valid if it can
be generated by a sequence of integers.
Given a sequence of integers, it is easy to compute its sign matrix. This problem is about the opposite
direction: Given a valid sign matrix, find a sequence of integers that generates the sign matrix. Note
that two or more different sequences of integers can generate the same sign matrix. For example, the
sequence (−2, 5, −3, 1) generates the same sign matrix as the sequence (−1, 5, −4, 2).
Write a program that, given a valid sign matrix, can find a sequence of integers that generates the
sign matrix. You may assume that every integer in a sequence is between −10 and 10, both inclusive.
Input
The input consists of T test cases. The number of test cases T is given in the first line of the input.
Each test case consists of two lines. The first line contains an integer n (1 ≤ n ≤ 10), where n is the
length of a sequence of integers. The second line contains a string of n(n + 1)/2 characters such that
the first n characters correspond to the first row of the sign matrix, the next n − 1 characters to the
second row, …, and the last character to the n-th row.
Output
For each test case, output exactly one line containing a sequence of n integers which generates the sign
matrix. If more than one sequence generates the sign matrix, you may output any one of them. Every
integer in the sequence must be between −10 and 10, both inclusive.
Sample Input
3
4
-+0++++–+
2
+++
5
++0+-+-+–+-+–
Sample Output
-2 5 -3 1
3 4
1 2 -3 4 -5

题目思路:首先吧,想到应该求出sum[0]到sum[n]的值,输出即可,而sum[i]的值可以设置在0到10之间,这样的话,任意的sum[i]与sum[i-1]只差的绝对值不会超过10,满足了题目要求的任意a[i]的绝对值小于等于10。
重点在于,这样的前缀和可以转化为拓扑排序,把i看做节点,当a[i]加到a[j]的值大于0时,即sum[j]-sum[i-1]大于0,这样连一条从j到i-1的边,反之,连一条,从i-1到j的边,这样,最大的边入度为0,进行拓扑排序即可。
注意(计算时加上0节点,因为要计算sum[0])

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
char a[20];
int G[20][20];
int rudu[20];
int vis[20];
int sum[20];
int n;
void toppo()
{
    int now=10,cnt=0;
    while(cnt<=n)
    {
        for(int i=0;i<=n;i++)
        {
            if(!rudu[i])
            {
                rudu[i]--;
                vis[i]=1;
                sum[i]=now;
                cnt++;
            }
        }
        now--;
        for(int i=0;i<=n;i++)
        {
            if(vis[i]==1)
            {
                for(int j=0;j<=n;j++)
                {
                    if(G[i][j])
                    {
                        rudu[j]--;
                    }
                }
                vis[i]=-1;
            }

        }


    }
}
void print()
{
    //cout<<111<<endl;
   // cout<<n<<endl;
    for(int i=1;i<=n;i++)
    {
       // cout<<sum[i]<<endl;
        printf("%d%c",sum[i]-sum[i-1],i==n?'\n':' ');
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        scanf("%s",a+1);
        memset(G,0,sizeof(G));
        memset(rudu,0,sizeof(rudu));
        memset(vis,0,sizeof(vis));
        int cnt=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                char c=a[cnt++];
//                cout<<c<<endl;
                if(c=='+')
                {
                    G[j][i-1]=1;
                    rudu[i-1]++;
                }
                else if(c=='-')
                {
                    G[i-1][j]=1;
                    rudu[j]++;
                }
            }
        }
//        for(int i=0;i<=n;i++)
//            cout<<rudu[i]<<endl;
        toppo();

        print();
       // cout<<111<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/CURRYWANG97/article/details/79523552
今日推荐