• 4.28考试总结(上午)


    1、挖地雷(lei.cpp)时空限制1000ms / 128MB

    题目描述

    在一个地图上有NN个地窖(N≤20),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。

    输入格式:(lei.in)

    有若干行。

    第1行只有一个数字,表示地窖的个数N。

    第2行有N个数,分别表示每个地窖中的地雷个数。

    第3行至第N+1行表示地窖之间的连接情况:

    第3行有n-1个数(0或1),表示第一个地窖至第2个、第3个、…、第n个地窖有否路径连接。如第3行为11000…0,则表示第1个地窖至第2个地窖有路径,至第3个地窖有路径,至第4个地窖、第5个、…、第n个地窖没有路径。

    第4行有n-2个数,表示第二个地窖至第3个、第4个、…、第n个地窖有否路径连接。

    … …

    第n+1行有1个数,表示第n-1个地窖至第n个地窖有否路径连接。(为0表示没有路径,为1表示有路径)。

    输出格式:(lei.out)

    有两行

    第一行表示挖得最多地雷时的挖地雷的顺序,各地窖序号间以一个空格分隔,不得有多余的空格。

    第二行只有一个数,表示能挖到的最多地雷数。

    输入输出样例

    输入样例#1:

    5
    
    10 8 4 7 6
    
    1 1 1 0
    
    0 0 0
    
    1 1
    
    1

    输出样例#1: 

    1 3 4 5
    
    27

    【思路】:

    就是直接用dp,用f[i]表示从i挖能挖到的最多的地雷,f[i]=max(f[i],f[j])

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn=999999999;
    const int minn=-999999999;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int n,pre[215],a[215],g[215][215],ans,t,f[215];
    void print(int x) {//递归输出路径
        if(pre[x]==0) {
            printf("%d",x);
            return ;
        }
        print(pre[x]);
        printf(" %d",x);//注意空格问题 
    }
    
    int main() {
        freopen("lei.in","r",stdin);
        freopen("lei.out","w",stdout);
        n=read();
        for(int i=1; i<=n; ++i) {//读入地雷
            scanf("%d",a+i);
        }
        for(int i=1; i<=n; ++i) {
            for(int j=i+1; j<=n; ++j) {
                int x=read();
                if(x==1)
                    g[i][j]=1;//存是否存在路径
            }
        }
        for(int i=1; i<=n; ++i) {
            for(int j=1; j<=n; ++j) {
                if((g[j][i]==1)&&(f[j]>f[i])) {
                    f[i]=f[j];
                    pre[i]=j;
                }
            }
            f[i]+=a[i];
            if (f[i]>ans) {
                ans=f[i];
                t=i;
            }
        }
        print(t);
        cout<<'
    ';
        printf("%d",ans);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    题目背景

    一年一度的“跳石头”比赛又要开始了!

    题目描述

    这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

    为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。

    输入输出格式

    第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L≥1 且 N≥M≥0。

    接下来 N 行,每行一个整数,第 i 行的整数Di​(0<Di​<L), 表示第 i 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。

    输入输出样例

    输入样例#1:
    25 5 2 
    2
    11
    14
    17 
    21
    输出样例#1: 
    4

    说明

    输入输出样例 1 说明:将与起点距离为 2和 14 的两个岩石移走后,最短的跳跃距离为 4(从与起点距离 17的岩石跳到距离 21 的岩石,或者从距离 21 的岩石跳到终点)。

    另:对于 20%的数据,0 ≤ M ≤ N ≤ 10。

    对于50%的数据,0 ≤ M ≤ N ≤ 100。

    对于 100%的数据,0 ≤ M ≤ N ≤ 50,000,1 ≤ L ≤ 1,000,000,000。

    【思路】:

    用二分答案来求。

    至于为什么用二分答案?学长说过只要出现上面加粗的字就用,嘿嘿

    为什么能用二分答案?

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn=999999999;
    const int minn=-999999999;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int a[2000002],mid,l,r,ans,L,N,M,now_juli,js;
    int check(int x) {
         now_juli=0,js=0;
        /*js是表示搬走的石头数量,now_juli是当前的石头离起点的距离*/
        for(int i=1; i<=N+1; ++i) {
            if(a[i]-now_juli<x) { //比较两点之间的距离
                js++;
            } else {
                now_juli=a[i];
            }
        }
        if(js>M) 
            return 0;
    }
    int main() {
    //    freopen("stone.in","r",stdin);
    //    freopen("stone.out","w",stdout);
        scanf("%d%d%d",&L,&N,&M);
        if(N==0&&M==0)
        {
            cout<<L;
            return 0;
        }
        int l=0,r=L;//初始化二分边界
        for(int i=1; i<=N; i++)
            scanf("%d",&a[i]);
        /*注意输入距离从近到远,答案有单调性*/
        a[N+1]=L;//注意设置终点,呜呜呜浪费我20分钟查错误 
        while(l<=r) {
            mid=(l+r)/2;
            if(check(mid)) { //
                l=mid+1;
                ans=mid;
            } else {     //
                r=mid-1;
            }
        }
        cout<<ans;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    3、花匠flower.cpp(时空限制1000ms / 128MB)

    题目描述

    花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。

    具体而言,栋栋的花的高度可以看成一列整数h1​,h2​,...,hn​。设当一部分花被移走后,剩下的花的高度依次为g1​,g2​,...,gm​,则栋栋希望下面两个条件中至少有一个满足:

    条件 A:对于所有g2i​>g2i−1​,g2i​>g2i+1​

    条件 BB:对于所有g2i​<g2i−1​,g2i​<g2i+1​

    注意上面两个条件在m=1时同时满足,当m > 1时最多有一个能满足。

    请问,栋栋最多能将多少株花留在原地。

    输入输出格式

    输入格式:

    第一行包含一个整数n,表示开始时花的株数。

    第二行包含n个整数,依次为h1​,h2​,...,hn​,表示每株花的高度。

    输出格式:

    一个整数m,表示最多能留在原地的花的株数。

    输入输出样例

    输入样例flower.in

    5
    
    5 3 2 1 2

    输出样例flower.out

    3

    说明

    【输入输出样例说明】

    有多种方法可以正好保留 3 株花,例如,留下第 1、4、5 株,高度分别为 5、1、2,满足条件 B。

    【数据范围】

    对于 20%的数据,n ≤ 10;

    对于30%的数据,n ≤ 25;

    对于 70%的数据n≤1000,0≤hi​≤1000;

    对于100%的数据,1≤n≤100,000,0≤hi​≤1,000,000,所有的hi​随机生成,所有随机数服从某区间内的均匀分布。

     【思路】:和合唱队形一样的思路。用二维数组表示到i点的最长上升和最长下降.

    然后统计波峰和波谷

     当出现这种情况时波谷+1(波谷怎么记录下面会有)

    当出现这个情况时波峰加1

    至于最后一种情况

    看i-2和i-1两个花,明显是不合法的,所以继续保留之前的结果就行了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn=999999999;
    const int minn=-999999999;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int n;
    int a[1000800],on[100800],down[100800];
    int main() {
        n=read();
        for(int i=1; i<=n; ++i) {
            a[i]=read();
        }
        on[1]=1,down[1]=1;
        for(int i=2; i<=n; ++i) {
            if(a[i]>a[i-1])
                on[i]=down[i-1]+1;
            else
                on[i]=on[i-1];
            if(a[i]<a[i-1])
                down[i]=on[i-1]+1;
            else
                down[i]=down[i-1];
        }
        cout<<max(on[n],down[n]);
        return 0;
    }
  • 相关阅读:
    IdentityServer4中AccessToken和IdentityToken中包含的Claims构成
    IdentityServer4授权类型(GrantType)对应的返回类型(ResponseType)
    IdentityServer4支持的授权类型以及组合
    基本技能-调试(android)
    通过修改返回包绕过部分机制的方法的小思考
    centos64位安装32位C/c++库
    redhat_suse双系统引导
    suse pshell连接不上
    vi复杂粘贴
    vi显示行号
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/10783212.html
Copyright © 2020-2023  润新知