这道题目思维+基础,好题目
拓扑排序
以后看到sij就要想到连续和转化为前缀和之差的思想,通过表格得到两两前缀和的大小关系,然后通过拓扑排序得到前缀和的大小序列,确定每个前缀和的大小,最后得到结果
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int maxn=11;
int e[maxn][maxn],b[maxn],in[maxn],sol[maxn];
int n,loc;
void topo()//基于栈的topo排序
{
int i;
int top=-1;//栈顶指针,一个没有额外使用内存,抽象的栈,巧妙的技巧
for(i=0;i<=n;i++)
{
if(!in[i])
{
in[i]=top;//判断完此节点知其入度为0,加入栈中,那么in[i]以后就没有什么作用了
//可用来存储入了栈的这一节点在栈中下一个元素的标号
top=i;
}
}
for(i=0;i<=n;i++)
{
//if(top==-1) break;
int t=top;
if(!t) loc=i;
sol[i]=t;
top=in[top];
for(int j=0;j<=n;j++)
{
if(e[t][j])
{
in[j]--;
if(!in[j])
{
in[j]=top;
top=j;
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
getchar();
while(t--)
{
int i,j;
scanf("%d",&n);
char c;
getchar();
memset(e,0,sizeof(e));
memset(in,0,sizeof(in));
for(i=1;i<=n;i++)
{
for(j=i;j<=n;j++)
{
scanf("%c",&c);
if(c=='+') { e[j][i-1]=1; in[i-1]++; }
if(c=='-') {e[i-1][j]=1; in[j]++; }
}
}
getchar();
topo();
b[0]=0;
for(i=loc-1;i>=0;i--)
{
int t1=sol[i],t2=sol[i+1];
if(!e[t1][t2]) b[t1]=b[t2];
else b[t1]=b[t2]+1;
}
for(i=loc+1;i<=n;i++)
{
int t1=sol[i],t2=sol[i-1];
if(!e[t2][t1]) b[t1]=b[t2];
else b[t1]=b[t2]-1;
}
for(i=1;i<n;i++) printf("%d ",b[i]-b[i-1]);
printf("%d\n",b[n]-b[n-1]);
}
return 0;
}