Given a sequence of integers, a1, a2,..., an , we define its sign matrix S such that, for 1ijn , Sij = `` + " if ai +...+ aj > 0 ; Sij = `` - " ifai +...+ 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
Your program is to read from standard 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(1n10) , 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
Your program is to write to standard 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
对于一个序列a1,a2,a3,....an,我们可以计算出一个符号矩阵S,就是上面右图矩阵,其中S(i,j)表示 ai+...+aj的正负号,给出序列不难求出矩阵,我们的任务是求出“逆问题”,即给出矩阵,求出序列,序列每个值大于-10小于10;
T0 T1 T2 T3 T4
(我在最前面加了一个0表示T0) 0 - + 0 +
-2 5 -3 1 ---> + + +
- -
+
如果用T(k)表示序列前k项和,那么S(i,j)= T(j )- T(i-1);S(i,j)正负知道,那么T(j)-T(i-1)的正负也就知道了,如果T(j)-T(i-1)='-',可以得出T(j)>T(i-1),让j指向i-1,建立边,可以得到一个拓扑排序图,
拓扑排序中被指向的点小于指向它的点,如果一个点没有任何点指向它,那么他是最大点,将拓扑排序最低端点赋值为10,因为每个序列中每个点都小于10 ,第二层T()值比最低端T()值小1,最多最多10层,做差肯定在-10~10之间,
以第一个样例分析
拓扑排序图解释,最底层是第一层,然后第二层,第三层,第四层,T(2)=10,T(4)=9,T(0)=8,T(3)=8,T(1)=7; a(1)=T(1)-T(0)=-1,a(2)=T(2)-T(1)=3,a(3)=-1.a(4)=1;
序列: -1,3,-2,-1;符合题意,输出任意一种序列就可以了,题目输出就是这么说的;
代码:
#include <iostream> #include <stdio.h> #include <queue> #include <string.h> #include <cmath> #include <stdlib.h> using namespace std; const int maxn=305; int sum[maxn];///表示前n项和 char str[maxn]; int d[maxn]; int head[maxn],tot; struct Edge { int v,next; }edge[maxn]; void init(int n) { tot=0; memset(head,-1,sizeof(head)); for(int i=0;i<=n;i++) sum[i]=10; } void addedge(int u,int v) { edge[tot].v=v; edge[tot].next=head[u]; head[u]=tot++; } void topo(int n) { queue<int>que; for(int i=0;i<=n;i++) if(d[i]==0) que.push(i); while(!que.empty()) { int u=que.front(); que.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; sum[v]=sum[u]-1; d[v]--; if(d[v]==0) que.push(v); } } } int main() { int t,n; int ans[maxn]; cin>>t; while(t--) { cin>>n; cin>>str; int k=0; memset(d,0,sizeof(d)); init(n); for(int i=1;i<=n;i++) { for(int j=i;j<=n;j++,k++) { if(str[k]=='-')///Si>Sj { addedge(i-1,j); d[j]++; } else if(str[k]=='+')///Sj>Si { addedge(j,i-1); d[i-1]++; } } } topo(n); for(int i=1;i<=n;i++) ans[i]=sum[i]-sum[i-1]; cout<<ans[1]; for(int i=2;i<=n;i++) cout<<" "<<ans[i]; cout<<endl; } return 0; }