zoukankan      html  css  js  c++  java
  • zoj1108 FatMouse's Speed

    给你每个物体两个参数,求最长的链要求第一个参数递增,第二个参数递减,要求输出任意最长路径。

    首先第一反应根据第二个参数排个序,然后不就是最长上升子序列的问题吗?

    O(nlogn)的复杂度,当然这样可以写,写法也不难。

    然后发现这个还是个DAG,也可以用拓扑排序来搞定,输出最长路径,复杂度O(n*n),更新的时候需要更新并记录每个点的前节点,最后倒序输出。

    第二种就当练练手吧

    先上第二种代码:

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<iostream>
    #include<vector>
    #include<cstring>
    #include<queue>
    using namespace std;
    int d;
    struct node
    {
        int x,y;
    }h[1005];
    vector<int> t[1005];
    int deg[1005];
    queue<int> q;
    int g[1005];
    int ans=0;
    int res=-1;
    int dp[1005];
    vector<int> s;
    void tp()
    {
        for(int i=0;i<d;i++)
        {
            if(deg[i]==0)
            {
                dp[i]=1;
                   q.push(i);
            }
        }
        while(!q.empty())
        {
            int xx=q.front();
            if(dp[xx]>ans)
            {
                ans=dp[xx];
                res=xx;
            }
            q.pop();
            for(int i=0;i<t[xx].size();i++)
            {
                int w=t[xx][i];
                deg[w]--;
                if(dp[w]<dp[xx]+1)
                {
                    dp[w]=dp[xx]+1;
                    g[w]=xx;
                }
                if(deg[w]==0)
                 q.push(w);
            }
        }
    }
    
    int main()
    {
        //freopen("input.txt","r",stdin);
        int a,b;
        memset(g,-1,sizeof(g));
       while(scanf("%d%d",&a,&b)==2)
       {
           h[d].x=a;
           h[d].y=b;
           d++;
       }
       for(int i=0;i<d;i++)
         for(int j=0;j<d;j++)
       {
           if(h[i].x<h[j].x&&h[i].y>h[j].y){
            t[i].push_back(j);
            deg[j]++;
           }
       }
       tp();
       printf("%d
    ",ans);
       s.push_back(res+1);
       while(g[res]!=-1)
       {
          s.push_back(g[res]+1);
           res=g[res];
       }
       int len=s.size();
       for(int i=len-1;i>=0;i--)
        printf("%d
    ",s[i]);
    }

    第一种代码稍后补上:

    参考http://blog.csdn.net/dangwenliang/article/details/5728363

    原理:O(N*N)的,一维,设dp[i]为以第i位为结尾的最长长度,dp[i]=max(dp[j])+1(j<i),然后记录前缀,输出路径。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<iostream>
    #include<vector>
    #include<cstring>
    #include<queue>
    using namespace std;
    int d;
    struct node
    {
        int x,y,r;
    }h[1005];
    int hh[1005];
    int g[1005];
    vector<int> t;
    bool cmp(node a,node b)
    {
        if(a.y>b.y)
        return 1;
        return 0;
    }
    int f[1005];
    int ans,res;
    int main()
    {
        //freopen("input.txt","r",stdin);
        int a,b;
        memset(g,-1,sizeof(g));
        while(scanf("%d%d",&a,&b)==2)
       {
           h[d].x=a;
           h[d].y=b;
           h[d].r=d;
           d++;
       }
       sort(h,h+d,cmp);
       hh[0]=1;
       int res=-1;
       ans=0;
       for(int i=1;i<d;i++)
       {
           hh[i]=1;
           for(int j=0;j<i;j++)
           {
               if(h[i].x>h[j].x&&hh[i]<hh[j]+1)
               {
                   hh[i]=hh[j]+1;
                   g[i]=j;
                   if(hh[i]>res)
                   {
                       ans=i;
                       res=hh[i];
                }
            }
        }
       }
       printf("%d
    ",res);
       t.push_back(ans);
       while(g[ans]!=-1)
       {
             t.push_back(g[ans]);
             ans=g[ans];
       }
       int len=t.size();
       for(int i=len-1;i>=0;i--)
       {
           printf("%d
    ",h[t[i]].r+1);
       }
    }

    然后来O(nlogn)算法。

    首先能这么做,要满足dp的两个根本原则:1.无后效性,每一个点的状态都由其前面的点决定

                                                           2.每一步都是当前那一个整体最优。

        我们必须用到二分,但是这个前面的点的序列是不连续的,所以我们需要选出前面的点中每一步中的最优,来组成一个"标杆队列",因为对于数和数之间的前后关系是重要的,但对于当前的数,前面的数的前后关系是不重要的,如果每一次二分,dp的同时维护那个"标杆队列",我们可以保证那个队列是最优的,那么下一个点也会是最优的,也可以保证结果是最优的。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<iostream>
    #include<vector>
    #include<cstring>
    #include<queue>
    using namespace std;
    int d=1;
    struct node
    {
        int x,y,r;
    }h[1005];
    int ans[1005];
    int hh[1005];
    int dp[1005];
    bool cmp(node a,node b)
    {
        if(a.y>b.y)
        return 1;
        else if(a.y==b.y&&a.x>b.x)
        return 1;
        return 0;
    }
    
    int main()
    {
        //freopen("input.txt","r",stdin);
        int a,b;
        while(scanf("%d%d",&a,&b)==2)
       {
           h[d].x=a;
           h[d].y=b;
           h[d].r=d;
           d++;
       }
       sort(h+1,h+d,cmp);
       for(int i=1;i<d;i++)
       ans[i]=10005;
       int len=0;
       for(int i=1;i<d;i++)
       {
           int t=lower_bound(ans+1,ans+d,h[i].x)-ans;
           ans[t]=h[i].x;
           dp[i]=t;
           len=max(len,t);
       }
       printf("%d
    ",len);
       int cc=len;
       int res=0;
       int f=10005;
       for(int i=d-1;i>0;i--)
       {
             if(len==0)
                break;
            if(dp[i]==len&&h[i].x<f)
             {
            hh[res++]=i;
               len--;
               f=h[i].x;
            }
       }
       for(int i=res-1;i>=0;i--)
      {
            printf("%d
    ",h[hh[i]].r);
      }
    }
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/acliang/p/4897712.html
Copyright © 2011-2022 走看看