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;
}