这道题目思维+基础,好题目
拓扑排序
以后看到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; }