zoukankan      html  css  js  c++  java
  • UVALive 4255 Guess

    这道题目让我学到了很多

    一道不走寻常路的题目,给定一串数列的 和 的正负号,即假设数列 为  a1,a2,a3.....an,则一致了 Sij的正负号或者是否等于0,Sij代表了 从 ai 到 aj的和。要你求出任意一种序列,满足题目给定的Sij条件

    确实是看了白书上的思路都还不太知道怎么写,然后看了LRJ的代码才知道原来还可以如此实现

    很容易联系到前缀和sum,也就是说我们现在 得到了 sum[i]-sum[j] (j<i) 的正负号情况,要求满足情况的数列,那我们如果能得到满足情况的 sum[],那数列的每个数岂不就是

    sum[i]-sum[i-1],那就是说我们得到合理的sum值,就相当于得到了最终结果

    LRJ的思路是用拓补排序,。。。哎,以前写过裸的拓补排序,但是一到这种关键题目,就联想不起来可以这样搞,即,我们根据已经得到的sum[i]-sum[j]的正负号,得到 sum[i]和sum[j]的相对大小关系,当然还有个sum[0]=0作为对照,根据大小关系来进行建边,则,进行一次拓补排序就可以轻松把sum进行排序,其实说到底,只要sum排好了序,问题就解了,前面所有的都是为这个做铺垫,。。。既然把sum从小到大  或者 从大到小 排了序,就手动 把 1-n负责给他们呗,然后他们一相减就是合理的数列值了

    题目里面有0,就代表某两个前缀和相等,在代码里用了 并查集合并 进行优化,不仅节省时间,还省去了处理相等的情况。

    确实学到了好多,本来有点无所下手,这道题目首先,根据题目给的条件联想,要得到最终结果,其实是先得到前缀和的结果,因为题目给的就是和之间的大小关系,肯定要联想到前缀和的,不然不可能直接得到结果。其次拓补排序这种很实用的算法,也要懂得利用起来

    其实我刚刚说了,所有处理的目的就是给 前缀和进行排序,前缀和顺序出来了,结果就出来了,所以也有人直接在读入的时候,读到+就对前面的sum--,读到+就对后面的--,这样sum的相对大小也可以出来。尽管没证明,好像这样做也可以,因为在扫第一行的时候,就把 sum1和其他sum的相对大小关系求出来了,然后扫第二行,就把sum2和除sum1以外的大小也求出来了,以此类推。。。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int n;
    char ch[60],S[15][15];
    int f[20];
    int findset(int x){
        if (x!=f[x]){
           return f[x]=findset(f[x]);
        }
        return x;
    }
    int G[15][15];
    int c[15],cnt,topo[15];
    bool dfs(int u)
    {
        c[u]=-1;
        for (int v=0;v<=n;v++) if (G[u][v]){
            if (c[v]<0) return false;
            else  if (!c[v] && !dfs(v)) return false;
        }
        c[u]=1;
        topo[cnt--]=u;
        return true;
    }
    bool toposort()
    {
        cnt=n;
        memset(c,0,sizeof c);
        for (int i=0;i<=n;i++) if (!c[i])
            if (!dfs(i)) return false;
        return true;
    }
    int sum[15];
    int main()
    {
        int t;
        scanf("%d",&t);
        while (t--){
            scanf("%d%s",&n,ch);
            for (int i=0;i<=n;i++) f[i]=i;
            int tmp=0;
            for (int i=1;i<=n;i++)
                for (int j=i;j<=n;j++){
                    S[i][j]=ch[tmp++];
                    if (S[i][j]=='0'){
                        f[findset(j)]=i-1;
                    }
                }
            memset(G,0,sizeof G);
            for (int i=1;i<=n;i++)
               for (int j=i;j<=n;j++){
               if (S[i][j]=='-') G[findset(j)][findset(i-1)]=1;
               else if (S[i][j]=='+') G[findset(i-1)][findset(j)]=1;
            }
            toposort();
            //for (int i=0;i<=n;i++) cout<<topo[i]<<endl;
            for (int i=0;i<=n;i++) sum[topo[i]]=i;
            for (int i=1;i<=n;i++){
                sum[i]=sum[f[i]];
                if (i>1) printf(" ");
                printf("%d",sum[i]-sum[i-1]);
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    leetcode59
    leetcode95
    leetcode96
    leetcode787
    leetcode150
    leetcode165
    leetcode739
    快速搭建:Djangorest-framework的restful项目
    编写部署用到的部分shell脚本收集
    pandas:dataframe删除某些不为non的行
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3754113.html
Copyright © 2011-2022 走看看