• 2016.8.29.第39套测试题


    描述(A 输入文件 : A.input 输出文件 : A.output)
    一个城市的构成是一颗n 个节点的树(2 ≤ n ≤ 200), 现在需要在树中找出两条不相交的路
    径(即两条路径不能有重边也不能有重点),使得路径的长度的乘积最大。

    解析:

    这道题很简单,因为说了是颗无环树,然后在树上找两条线不想交,乘积最大。很容易想到,枚举边,然后从两个断点的子树分别找两条最长路径,就是最大值。找最长路径方法呢,因为数据很小,可以直接暴力出所有儿子的最深长度,然后选两个最长的相加。当然更简单的就是先找个点的最深到i,再从i搜条最长路到j,那么i,j就是最长的路径。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<fstream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    ifstream fin ("A.input");
    ofstream fout ("A.output");
    struct stu{
        int x,y;
    }con[205];
    int a,b,f[205][205],n,ans,g[205][205];
    bool use[205];
    int find(int v)
    {
        int ma=0;
        use[v]=false;
        for(int i=1;i<=n;i++)
        if(f[v][i]&&use[i]) {g[v][i]=1+find(i); ma=max(ma,g[v][i]);}
        return ma;
    }
    int main()
    {
        fin>>n;
        for(int i=1;i<=n-1;i++)
        {
            fin>>a>>b;
            f[a][b]=f[b][a]=1;
            con[i].x=a;
            con[i].y=b;
        }
        for(int i=1;i<=n-1;i++)
        {
            memset(use,true,sizeof(use));
            memset(g,0,sizeof(g));
            int q3=0;
            a=con[i].x;
            b=con[i].y;
            f[a][b]=f[b][a]=0;
            use[a]=use[b]=false;
            int q1=find(a);
            for(int i=1;i<=n;i++) 
            if(g[a][i]>=q3) q1=q3,q3=g[a][i];
            else if(g[a][i]>q1) q1=g[a][i];//少了这一步就少了90分 
            q1+=q3,q3=0;
            int q2=find(b);
            for(int i=1;i<=n;i++) 
            if(g[b][i]>=q3) q2=q3,q3=g[b][i];
            else if(g[b][i]>q2) q2=g[b][i];//
            q2+=q3;
            if(q1*q2>ans) ans=q1*q2;
            f[a][b]=f[b][a]=1;
        }
        fout<<ans<<endl;
        return 0;
    }

    错因:

    找两条最长的子路时,比第一短第二长的时候没有算进去。

    描述(B 输入文件 : B.input 输出文件 : B.output)
    有n 个人需要看医生, 其中第i 个人需要看医生的次数是ai, 一开始从1 到n 依次排列组成
    一个等待队伍, 每个人依次看医生, 那么每个人看完医生有两种情况, 第一种情况:他
    已经看够他需要看医生的次数,那么他会离开。第二种情况:他还需要看医生,那么他就
    会选择重新站在队伍的最后。选择医生想知道,当他看过k 次病人之后,这个等待队伍是
    什么样。

    解析:

    这道题也很简单,就是k的问题,k 的范围是1e14过于的大了。所以需要把k的范围降下来,可以降到1e5内。如何降,其实就是找出医生在第几轮的时候结束看病。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<fstream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int tot,g[100005],a[100005],b[100005],n,m;
    struct stu{
        int num;
        ll sum;
    }c[100005];
    ll k,q,s;
    int main()
    {
        freopen("B.input","r",stdin);
        freopen("B.output","w",stdout);
        scanf("%d %I64d",&n,&k);//输入的时候用的d,我操 
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+n+1);
        for(int i=1;i<=n;i++)
        if(b[i]!=b[i-1])
        {
            tot++;
            c[tot].num++;
            c[tot].sum=b[i];
        }
        else c[tot].num++;
        tot=0,m=n;
        while(q<k)
        {
            tot++;
            q=(ll)(q+(c[tot].sum-c[tot-1].sum)*m);
            m=m-c[tot].num;
        }
        m+=c[tot].num;
        k=(ll)(k-(q-(c[tot].sum-c[tot-1].sum)*(m)));
        s=k/m+c[tot-1].sum;//之前漏了这两部 
        k=k%m;//差值并不是1 
        for(int i=1;i<=n;i++)
        {
            if(a[i]>s&&m) 
              {
                if(k<=0)
                {m--,printf("%d",i);
                 if(m>0) printf(" ");}
                else {
                       if(a[i]>s+1) g[0]++,g[g[0]]=i;
                        else m--;
                     }
                 k--;    
              }
        
        }
        
        for(int i=1;i<=g[0];i++)
        {
            m--,printf("%d",g[i]);
            if(m>0) printf(" ");
        }
        return 0;
    }

    描述(C 输入文件 : C.input 输出文件 : C.output)
    有n 个任务需要你去完成,这些任务分布在3 个不同的房间,编号为1,2,3, 其中有些任务
    必须在一些其他的任务完成之后才能完成。现在知道完成一个任务需要1 的时间,现在知
    从房间1 到2,2 到3,3 到1 需要1 的时间,从1 到3,2 到1,3 到2 需要2 的时间。现
    在你可以选择你一开始的房间,问完全所有任务的最短时间是多少,保证可以完成。

    解析:

    cx用暴力,直接枚举每一个房间,不停循环,有任务做,没任务下一个。正解差不多,之说用了个拓扑排序和队列,更简单了,也是循环房间。然而我一个傻逼根本没有管房间,最后TLEl 80分...感觉今天做的好垃圾,不想多说了。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<fstream>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #define p 100000000
    using namespace std;
    ifstream fin ("C.input");
    ofstream fout ("C.output");
    int n,c[205],deg[205],in[205],f[205][205],q[205],x,ans=p;
    int move(int a,int b)
    {
        if(b==a) return 0;
        if((b-a)==1||(b-a)==-2) return 1;
        return 2;
    }
    queue<int>que[5];
    int dp(int v)
    {
        int m=0;
        int number=0;
        memcpy(deg,in,sizeof(in));
        for(int i=1;i<=n;i++) if(!in[i]) que[c[i]].push(i),number++;
        int cur=v;
        while(number)
        {
            while(!que[cur].empty())
            {
                int u=que[cur].front();
                que[cur].pop();
                number--;
                for(int i=1;i<=n;i++)
                if(f[u][i])
                {
                    if(--deg[i]==0) que[c[i]].push(i),number++;
                }
            }
            if(!number) break;
            m++;
            cur++;
            if(cur>3) cur-=3;
        }
        return m+n;
    }
    int main()
    {
        fin>>n;
        for(int i=1;i<=n;i++) fin>>c[i];
        for(int i=1;i<=n;i++) 
        {
            fin>>in[i];
            for(int j=1;j<=in[i];j++)
            {
                fin>>x;
                f[i][x]=f[x][i]=1;
            }
            
        }
        for(int i=1;i<=3;i++) 
        ans=min(ans,dp(i));
        fout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    关于服务器并发量的简单计算
    重温Android和Fragment生命周期
    JVM类加载机制
    设计六大原则总结
    Android Navigation使用
    Android BrocastReceiver解析
    Android LiveData使用
    Android Service解析
    Activity的生命周期和启动模式
    Java四种引用
  • 原文地址:https://www.cnblogs.com/fisch/p/5819396.html
Copyright © 2020-2023  润新知