zoukankan      html  css  js  c++  java
  • cqyz oj | 猜序列

    Description

      对于一个序列a[1],a[2],…,a[n],我们可以计算出一个符号矩阵S,其中s[i][j]=a[i]+…+a[j]的正负号:连加和大于0则s[i][j]="+",小于0则s[i][j]="-",等于0则s[i][j]="0"。例如序列:-1,5,-4,2的矩阵如下: 
        
      根据序列A不难算出上述符号矩阵。你的任务上求解它的逆问题,即给出一个符号矩阵,找出一个对应的序列。输入保证存在一个满足上述条件的序列。可能满足的序列有多个,最大元素和最小元素尽量接近的解。

    Input

      第1行为整数T,表示数据组数。  每组数据包含两行,第1行为整数n,表示序列长度。第2行有n*(n+1)/2个字符,有符号矩阵的每一行按照从上到下的顺序连接而成。

    Output

      对于每组数据,在一行上输出n个绝对值不超过10的整数,即序列A。要求最大元素和最小元素尽量接近的解。

    Sample Input 1 

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

    Sample Output 1

    -1 3 -2 1
    1 1 
    1 1 -2 3 -4

    Hint

    1<=T<=100
    1<=n<=10

    本题的核心思路是转化。

    s[i][j]为连续子序列和,可以转化为sum[j]-sum[i-1](前缀和)。

    由题目所给信息可以判断出 sum[j] 与 sum[i-1] 的大小关系,于是可以把 sum 的下标看作图的顶点,

    将 sum[i-1]<sum[j] 转化为由 i-1 到 j 的一条有向边。

    因为图中不可能存在环,所以该图为DAG图,又因为A[i]=A[i]-A[i-1],

    所以可以运用拓扑排序把sum计算出来,进而求得A序列。

    需要注意的是要使序列中最大值与最小值尽量接近,且序列为整数,

    则sum之间的最小差值为1,进行拓扑排序BFS,求得所有sum。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    const int maxn = 15;
    
    int n;
    vector<int> g[maxn];
    int rd[maxn];
    void input() {
        scanf("%d
    ", &n);
        for(int i=0; i<=n; i++)
            rd[i] = 0, g[i].clear();
        for(int i=1; i<=n; i++)
            for(int j=i; j<=n; j++) {
                char ch=getchar();
                if(ch == '+') {
                    g[i-1].push_back(j);
                    rd[j]++;
                }
                else if(ch == '-') {
                    g[j].push_back(i-1);
                    rd[i-1]++;
                }
            }
    }
    
    int sum[maxn];
    void BFS() {
        memset(sum, 0, sizeof(sum));
        queue<int> Q;
        for(int i=0; i<=n; i++)
            if(!rd[i]) Q.push(i);
        while(!Q.empty()) {
            int u = Q.front(); Q.pop();
            for(int i=0; i<g[u].size(); i++) {
                int v = g[u][i];
                sum[v] = max(sum[v], sum[u]+1);
                if(!--rd[v]) Q.push(v);
            }
        }
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            input();
            BFS();
            for(int i=1; i<n; i++) printf("%d ", sum[i]-sum[i-1]);
            printf("%d
    ", sum[n]-sum[n-1]);
        }
        return 0;
    }
    /*
    3
    4
    -+0++++--+
    2 
    +++ 
    5 
    ++0+-+-+--+-+--
    
    */
    View Code
  • 相关阅读:
    Vue.js双向绑定的实现原理和模板引擎实现原理(##########################################)
    JavaScript:最烂与最火
    JSP九大内置对象和四种属性范围解读
    codevs1009
    hdu 4869 Turn the pokers (2014多校联合第一场 I)
    OpenGL——点的绘制(使用OpenGL来绘制可旋转坐标系的螺旋线)
    nodejs 批处理运行 app.js
    jquery更新后怎样在一个站点中使用两个版本号的jQuery
    vs连接mysql出错解决方法
    uva 10627
  • 原文地址:https://www.cnblogs.com/de-compass/p/11800071.html
Copyright © 2011-2022 走看看