题意:
然后给定这个矩阵,然后让你构造a序列。
理解:每个符号表示的Bij = ai+.....+aj,那么可以写成前缀和相减的形式,前缀和用S表示,则B[ij] = S[j]-S[i-1];
由那个矩阵可以得出 S[j]-S[i-1] > 0; S[j]-S[i-1] < 0; S[j]-S[i-1] = 0;
如果要满足 S[j]-S[i-1] > 0 ,则可以使 S[j]-1 = S[i-1]; (1)
然后把S[j]-S[i-1] < 0这种情况添一个负号, = 0情况不管
现在所有关系式都成了 > 的这种形式
然后把每一个点的前缀和想象成一个点,S[j]-S[i-1] > 0 就建一条s[j]->s[i-1]的边,另一种形式就反向建边;
最后使用一次拓扑排序,由(1)这个条件得,每个点指着的下一个点等于这个点的值减去1就行了,如果有多个点指向这个点则要取最小,不取最小可能会和以前更新的点冲突,即不能满足S[j]-S[i-1] > 0 或 S[i-1]-S[j] > 0 z条件。
每个点赋初值可以任意值,因为是前缀和的关系,减去之后都一样。
CODE:
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 15;
int n;
char s[maxn*maxn]; ///存图用的字符串
int v[maxn]; ///把前缀和看成点
int in[maxn]; ///入度
vector<int> maze[maxn];///存边
void INIT() ///初始化
{
for(int i = 0 ;i < maxn; i++)
{
maze[i].clear();
in[i] = 0;
v[i] = 0;
}
}
void topsort() ///拓扑排序
{
queue<int> q;
for(int i = 0;i <= n;i++)
{
if(in[i] == 0)
q.push(i);
}
while(!q.empty())
{
int st = q.front();
q.pop();
for(int i = 0; i < maze[st].size(); i++)
{
int en = maze[st][i];
v[en] = min(v[en],v[st]-1); ///存能取到的最小值,不然可能会和之前更新的一些点冲突
q.push(en);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
INIT();
scanf("%d",&n);
scanf("%s",s);
int cnt = 0;
for(int i = 1;i <= n;i++)
{
for(int j = i;j <= n;j++)
{
if(s[cnt] == '+')
{
maze[j].push_back(i-1);
in[i-1]++;
}
else if(s[cnt] == '-')
{
maze[i-1].push_back(j);
in[j]++;
}
cnt++;
}
}
topsort();
for(int i = 1;i <= n;i++)
printf("%d ",v[i]-v[i-1]);
puts("");
}
return 0;
}