题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36239
题意:给定S( i , j ) , ( i <= j) 的矩阵表示一个数字序列第i个到第j个元素的连续和的符号,‘+’,‘-’,‘0’,求序列的一种可能值。
思路:矩阵中的每个元素都可以看作是序列前缀和之差的结果,若设sum(i)为前i个元素的前缀和,则S( i, j )表示sum(j)- sum(i)的结果的符号,可以从确定关系的两个前缀和间连一条有向边,从小的指向大的(反之亦可),然后进行拓扑排序得到sum(i)的一种大小关系。最后对sum(i)依次赋值,即可得到序列。
敲了两种版本的拓扑排序,dfs 和 bfs两种版本
代码:
dfs版
#include<bits/stdc++.h>
using namespace std;
int G[15][15], vis[15], rec[15][15], ans[15], Ans[15];
int len, n;
void dfs(int u){
vis[u] = 1;
for(int i = 0; i <= n; i++){
if(!vis[i] && G[u][i]) dfs(i);
}
ans[len--] = u; //记录路径,从后往前记录
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
len = n;
memset(G, 0, sizeof(G));
memset(vis, 0, sizeof(vis));
memset(rec, 0, sizeof(rec));
char a;
getchar();
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j++){
scanf("%c", &a);
if(a == '+') G[i-1][j] = 1;
else if(a == '-') G[j][i-1] = 1;
else if(a == '0') rec[i-1][j] = rec[j][i-1] = G[i-1][j] = 1;
}
}
for(int i = 0; i <= n; i++)
if(!vis[i]) dfs(i);
Ans[ans[0]] = 0;
for(int i = 1; i <= n; i++){ // 对找到的前缀和序列赋值
if(rec[ans[i]][ans[i-1]]) Ans[ans[i]] = Ans[ans[i-1]];
else Ans[ans[i]] = Ans[ans[i-1]] + 1;
}
for(int i = 1; i <= n; i++){
printf("%d%c", Ans[i]-Ans[i-1], i == n?'\n':' ');
}
}
return 0;
}
bfs版
#include<bits/stdc++.h>
using namespace std;
int G[15][15], rec[15], cnt, n, ans[15]; // rec[i]数组记录可能比第i个元素小的序列元素的数量
void bfs(){
queue<int> q;
while(!q.empty()) q.pop();
for(int i = 0; i <= n; i++) if(rec[i] == 0) q.push(i);
while(!q.empty()){
int sz = q.size();
for(int i = 0; i < sz; i++){
int u = q.front(); q.pop();
ans[u] = cnt; // 对找到的前缀和序列赋值
for(int v = 0; v <= n; v++){
if(G[u][v]){
rec[v]--;
if(rec[v] == 0) q.push(v);
}
}
}
cnt++;
}
}
int main(){
int t;
scanf("%d", &t);
while(t--){
cnt = 0;
char tmp;
scanf("%d", &n);
memset(G, 0, sizeof(G));
memset(rec, 0, sizeof(rec));
getchar();
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j++){
scanf("%c", &tmp);
if(tmp == '+') G[i-1][j] = 1, rec[j]++;
else if(tmp == '-') G[j][i-1] = 1, rec[i-1]++;
}
}
bfs();
for(int i = 1; i <= n; i++){
printf("%d%c", ans[i]-ans[i-1], i == n ? '\n' : ' ');
}
}
return 0;
}