zoukankan      html  css  js  c++  java
  • uva 1423 / Guess

    Given a sequence of integers, a1, a2,..., an , we define its sign matrix S such that, for 1$ le$i$ le$j$ le$n , Sij = `` + " if ai +...+ aj > 0 ; Sij = `` - " if ai +...+ aj < 0 ; and Sij = ``0" otherwise.

    For example, if (a1, a2, a3, a4) = (- 1, 5, - 4, 2) , then its sign matrix S is a 4×4 matrix:


      1 2 3 4
    1 - + 0 +
    2   + + +
    3     - -
    4       +


    We say that the sequence (-1, 5, -4, 2) generates the sign matrix. A sign matrix is valid if it can be generated by a sequence of integers.

    Given a sequence of integers, it is easy to compute its sign matrix. This problem is about the opposite direction: Given a valid sign matrix, find a sequence of integers that generates the sign matrix. Note that two or more different sequences of integers can generate the same sign matrix. For example, the sequence (-2, 5, -3, 1) generates the same sign matrix as the sequence (-1,5, -4,2).

    Write a program that, given a valid sign matrix, can find a sequence of integers that generates the sign matrix. You may assume that every integer in a sequence is between -10 and 10, both inclusive.

    Input 

    Your program is to read from standard input. The input consists of T test cases. The number of test cases T is given in the first line of the input. Each test case consists of two lines. The first line contains an integer n (1$ le$n$ le$10) , where n is the length of a sequence of integers. The second line contains a string of n(n + 1)/2 characters such that the first n characters correspond to the first row of the sign matrix, the next n - 1 characters to the second row, ... , and the last character to the n -th row.

    Output 

    Your program is to write to standard output. For each test case, output exactly one line containing a sequence of n integers which generates the sign matrix. If more than one sequence generates the sign matrix, you may output any one of them. Every integer in the sequence must be between -10 and 10, both inclusive.

    Sample Input 

    3 
    4 
    -+0++++--+ 
    2 
    +++ 
    5 
    ++0+-+-+--+-+--
    

    Sample Output 

    -2 5 -3 1 
    3 4 
    1 2 -3 4 -5
    
    LRJ的代码看不懂。。。然后发现http://blog.csdn.net/wiking__acm/article/details/8660931这位大神的代码和解说都比较易懂,于是照敲了一遍,很纠结地A了。
    其实就是拓扑排序,删除入度为零的点,删除其指出的边,开始觉得有点像差分约束题,但差分约束貌似只能判断有无解,而无法构造解。。。不过问题建模是一样的,不等式组,构造连接图:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<queue>
    #include<string>
    #include<cmath>
    #include<fstream>
    #include<iomanip>
    #include<climits>
    #include<cfloat>
    
    using namespace std;
    
    #define MAX_INT 0x7fffffff
    #define MAX_LL 0x7fffffffffffffff
    #define ULL unsigned long long
    #define LL long long
    #define MAX(x,y) ((x) > (y) ? (x) : (y))
    #define MIN(x,y) ((x) < (y) ? (x) : (y))
    
    #define MAXN 13
    int n;
    int map[MAXN][MAXN];
    int degree[MAXN];
    int s[MAXN];
    char text[1000];
    
    void Topsort(){
        int cnt=0,cur=-10;
        while(cnt<n+1){
            int flag[MAXN];
            memset(flag, 0, sizeof(flag));          //标记出入度为0的点
            for(int i=0; i<=n; i++) if(!degree[i]){
                degree[i]=-1;
                flag[i]=1;
                s[i]=cur;                           //构造解
                cnt++;
            }
            cur++;                                  //删除由标记点指出的弧
            for(int i=0; i<=n; i++) if(flag[i]){    
                for(int j=0; j<=n; j++) if(map[i][j]){
                    degree[j]--;
                }
            }
        }
    }
    
    void ini(){
        memset(map, 0, sizeof(map));
        memset(degree, 0, sizeof(degree));
    }
    
    int main(){
        //freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        int cas;
        scanf(" %d",&cas);
        while(cas--){
            scanf(" %d%s",&n,text);
            ini();
            int c=0;
            for(int i=1; i<=n; i++)
                for(int j=i; j<=n; j++){
                    if(text[c]=='+'){               //加边,s[j]-s[i-1]>0则i-1指向j,
                        map[i-1][j]=1;  degree[j]++;
                    }
                    else if(text[c]=='-'){
                        map[j][i-1]=1;  degree[i-1]++;
                    }
                    c++;
                }
            Topsort();                              //拓扑排序
            for(int i=1; i<=n; i++)
                printf("%d%c",s[i]-s[i-1],(i==n ? '
    ':' '));
        }
        return 0;
    }
    
  • 相关阅读:
    【C语言入门教程】5.1 函数说明 与 返回值
    【C语言入门教程】4.10 综合实例
    【C语言入门教程】4.9 指向指针的指针
    【C语言入门教程】4.8 指针数组
    【C语言入门教程】4.7 指针的地址分配
    Windows 7 共享文件夹 给 VirtualBox 中的 Ubuntu 14
    【C语言入门教程】4.6 指针 和 数组
    Ubuntu 12/14 个性化配置
    【C语言入门教程】4.5 指针变量的定义与引用
    【C语言入门教程】4.4 指针 与 指针变量
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3271792.html
Copyright © 2011-2022 走看看