zoukankan      html  css  js  c++  java
  • UVA1423

    link

    私以为,此题可以是一道不错的拓扑排序板题。

    题意:给定一个 (n imes n) 的半矩阵 (S),矩阵中每个位置的值 (S_{i,j}) 表示数列 ( ext{a})(i)(j) 的区间和的正负关系,分 (+,-,0) 三种。

    求解一个数列的最简便的方法就是先知道它的前缀和,那么我们把这题转换一下:

    (S_{i,j}=+),则 (sum[j]-sum[i-1]>0)(sum[j]>sum[i-1]),可以认为 (j) 的优先级比 (i-1) 高,从 (j)(i-1) 连一条边,相应地,(i-1) 入度加一。

    (S_{i,j}=-) 则与上面相反。

    (S_{i,j}=0),则不连边。

    这么转换,就可以确定 (1)(n) 的前缀和的大小关系,当前入度为零的点优先级一定最大,若有多个则顺着来就行。于是把建出来的图跑一边拓扑排序就可以了。

    #include <bits/stdc++.h>
    
    #define N 20
    
    using namespace std;
    
    template <typename T>
    inline int read (T &a) {
    	T x = 0, f = 1;
    	char ch = getchar ();
    	while (! isdigit (ch)) {
    		(ch == '-') and (f = 0);
    		ch = getchar ();
    	}
    	while (isdigit (ch)) {
    		x = (x << 1) + (x << 3) + (ch xor '0');
    		ch = getchar ();
    	}
    	return a = f ? x : -x;
    }
    template <typename T, typename ...A>
    inline void read (T &t, A &...a) {
    	read (t), read (a...);
    }
    template <typename T>
    inline void print (T x) {
    	if (x < 0) putchar ('-'), x = -x;
    	if (x > 9) print (x / 10);
    	putchar (x % 10 + '0');
    }
    
    char s[110];
    int ind[N], p[N][N], tot; // 入度,存图,当前的矩阵位置
    int t, sum[N], ans[N], n;
    bool vis[N];
    
    void tops () { // 经典拓扑排序,每次找入度为零的点,
    	int num = 10, cnt = 0;
    	while (cnt <= n) {
    		memset (vis, 0, sizeof vis);
    		for (int i = 0; i <= n; i++) {
    			if (ind[i]) continue;
    			sum[i] = num;
    			ind[i]--, cnt++;
    			vis[i] = 1;
    		} // 找点
    		for (int i = 0; i <= n; i++) {
    			if (! vis[i]) continue;
    			for (int j = 0; j <= n; j++) {
    				if (p[i][j]) ind[j]--;
    			} // 将与处理了的点相连的点的度数减一
    		}
    		num--;
    	}
    }
    
    signed main () {
    	read (t);
    	while (t--) {
    		memset (ind, 0, sizeof ind);
    		memset (p, 0, sizeof p);
    		read (n), scanf ("%s", s);
    		tot = 0;
    		for (int i = 1; i <= n; i++) { // 遍历矩阵,建图
    			for (int j = i; j <= n; j++) {
    				char c = s[tot++];
    				if (c == '+') {
    					p[j][i - 1] = 1;
    					ind[i - 1]++;
    				} else if (c == '-') {
    					p[i - 1][j] = 1;
    					ind[j]++;
    				}
    			}
    		}
    		tops ();
    		for (int i = 1; i <= n; i++) {
    			printf ("%d%c", sum[i] - sum[i - 1], " 
    "[i == n]);
    		}
    	}
    }
    
  • 相关阅读:
    PAT 1088. Rational Arithmetic
    PAT 1087. All Roads Lead to Rome
    PAT 1086. Tree Traversals Again
    PAT 1085. Perfect Sequence
    PAT 1084. Broken Keyboard
    PAT 1083. List Grades
    PAT 1082. Read Number in Chinese
    求最大公因数
    [转载]Latex文件转成pdf后的字体嵌入问题的解决
    [转载]Matlab有用的小工具小技巧
  • 原文地址:https://www.cnblogs.com/codingxu/p/15486795.html
Copyright © 2011-2022 走看看