• 9.23 noip模拟试题


     

    Problem 1 抓牛(catchcow.cpp/c/pas)

    【题目描述】

           农夫约翰被通知,他的一只奶牛逃逸了!所以他决定,马上出发,尽快把那只奶牛抓回来.

    他们都站在数轴上.约翰在N(O≤N≤100000)处,奶牛在K(O≤K≤100000)处.约翰有两种办法移动,步行和瞬移:步行每秒种可以让约翰从x处走到x+l或x-l处;而瞬移则可让他在1秒内从x处消失,在2x处出现.然而那只逃逸的奶牛,悲剧地没有发现自己的处境多么糟糕,正站在那儿一动不动.

           那么,约翰需要多少时间抓住那只牛呢?

    【输入格式】

    仅有两个整数N和K

    【输出格式】

    最短时间

    【样例输入】

    5 17

    【样例输出】

    4

    裸bfs

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    int n,k,f[200010];
    struct node{
        int x,t;
    };
    queue<node>q;
    int Bfs(){
        q.push((node){n,0});
        f[n]=1;
        while(!q.empty()){
            int r=q.front().x;
            int p=q.front().t;
            q.pop();
            if(r==k)return p;
            if(r+1<=100000&&f[r+1]==0){
                f[r+1]=1;q.push((node){r+1,p+1});
            }
            if(r-1>=0&&f[r-1]==0){
                f[r-1]=1;q.push((node){r-1,p+1});
            }
            if(r*2<=100000&&f[r*2]==0){
                f[r*2]=1;q.push((node){r*2,p+1});
            }
        }
    }
    int main()
    {
        freopen("catchcow.in","r",stdin);
        freopen("catchcow.out","w",stdout);
        scanf("%d%d",&n,&k);
        printf("%d
    ",Bfs());
        return 0;
    }
    View Code

    Problem 2 路面修整(grading.cpp/c/pas)

    【题目描述】

    FJ打算好好修一下农场中某条凹凸不平的土路。按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中。 整条路被分成了N段,N个整数A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。FJ希望找到一个恰好含N个元素的不上升或不下降序列B_1, ... , B_N,作为修过的路中每个路段的高度。由于将每一段路垫高或挖低一个单位的花费相同,修路的总支出可以表示为: |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N| 请你计算一下,FJ在这项工程上的最小支出是多少。FJ向你保证,这个支出不会超过2^31-1。【输入格式】
     第1行: 输入1个整数:N * 第2..N+1行: 第i+1行为1个整数:A_i

    【输出格式】
    第1行: 输出1个正整数,表示FJ把路修成高度不上升或高度不下降的最小花费

    【样例输入】

    7
    1
    3
    2
    4
    5
    3
    9

    【样例输出】

    3

    【样例解释】

    FJ将第一个高度为3的路段的高度减少为2,将第二个高度为3的路段的高度增加到5,总花费为|2-3|+|5-3| = 3,并且各路段的高度为一个不下降序列 1,2,2,4,5,5,9。

    开始想错了后来发现没时间改了... 乱搞40分

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 2010
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,a[maxn],b[maxn],c[maxn],d[maxn],r,q[maxn],pre[maxn],A,B,p;
    int Abs(int a){
        return a<0?-a:a;
    }
    void LIS(){
        for(int i=1;i<=n;i++){
            int x=a[i];
            if(x>=c[r]){
                pre[i]=q[r];c[++r]=x;
                q[r]=i;continue;
            }
            int p=lower_bound(c+1,c+1+r,x)-c;
            pre[i]=q[p-1];q[p]=i;c[p]=x;
        }
    }
    int main()
    {
        freopen("grading.in","r",stdin);
        freopen("grading.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        LIS();p=q[r];
        while(p){
            b[p]=1;
            q[r--]=p;
            p=pre[p];
        }
        for(int i=1;i<=n;i++){
            if(b[i]==1)continue;
            int s1,s2=inf;
            for(int k=i-1;k>=1;k--)
                if(b[k]){
                    s1=a[k];break;
                }
            for(int k=i+1;k<=n;k++)
                if(b[k]){
                    s2=a[k];break;
                }
            A+=min(Abs(a[i]-s1),Abs(a[i]-s2));
        }
        memset(c,0,sizeof(c));
        memset(q,0,sizeof(q));
        memset(b,0,sizeof(b));
        memset(pre,0,sizeof(pre));
        r=p=0;
        for(int i=1;i<=(n+1)/2;i++)
            swap(a[i],a[n-i+1]);
        LIS();p=q[r];
        while(p){
            b[p]=1;
            q[r--]=p;
            p=pre[p];
        }
        for(int i=1;i<=n;i++){
            if(b[i]==1)continue;
            int s1,s2=inf;
            for(int k=i-1;k>=1;k--)
                if(b[k]){
                    s1=a[k];break;
                }
            for(int k=i+1;k<=n;k++)
                if(b[k]){
                    s2=a[k];break;
                }
            B+=min(Abs(a[i]-s1),Abs(a[i]-s2));
        }
        printf("%d
    ",min(A,B));
        return 0;
    }
    View Code

    正解dp

    /*
    正解 离散化+dp 
    f[i][j]表示前i个元素构成的不降序列在最后的大小为j的最小消耗 
    f[i][j]=min(f[i-1][k]+Abs(a[i]-b[j]))
    n*n*n Tle
    因为f[i][j-1]这个状态已经是找过f[i-1][1....j-1]的最小的了
    所以直接用 在考虑一下新的f[i-1][j] 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 2010
    using namespace std;
    int n,a[maxn],b[maxn],f[maxn][maxn],ans;
    int cmp(int x,int y){
        return x>y;
    }
    int Abs(int x){
        return x<0?-x:x;
    }
    int main()
    {
        freopen("grading.in","r",stdin);
        freopen("grading.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(j==1)f[i][j]=f[i-1][j]+Abs(a[i]-b[j]);
                else f[i][j]=min(f[i][j-1],f[i-1][j]+Abs(a[i]-b[j]));
        ans=f[n][n];
        sort(b+1,b+1+n,cmp);
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(j==1)f[i][j]=f[i-1][j]+Abs(a[i]-b[j]);
                else f[i][j]=min(f[i][j-1],f[i-1][j]+Abs(a[i]-b[j]));
        ans=min(ans,f[n][n]);
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    Problem 3 教主的魔法(magic.cpp/c/pas)

    【题目描述】

    教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。

    每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)

    CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。

    WD巨懒,于是他把这个回答的任务交给了你。

    【输入格式】

     第1行为两个整数N、Q。Q为问题数与教主的施法数总和。

     第2行有N个正整数,第i个数代表第i个英雄的身高。

     第3到第Q+2行每行有一个操作:

    (1)若第一个字母为“M”,则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。

    (2)若第一个字母为“A”,则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。

    【输出格式】

         对每个“A”询问输出一行,仅含一个整数,表示闭区间 [L, R] 内身高大于等于C的英雄数。

     【样例输入】

    5 3

    1 2 3 4 5

    A 1 5 4

    M 3 5 1

    A 1 5 4

    【样例输出】

    2

    3

    【数据范围】

    【输入输出样例说明】

    原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。

    【数据范围】

    对30%的数据,N≤1000,Q≤1000。

    对100%的数据,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000

    正解好像是分块 然而对于我这应付noip的蒟蒻来说并没有打算学~~

    暴力100(数据弱~~)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 1000010
    using namespace std;
    int n,m,a[maxn];
    char c[5];
    int main()
    {
        //freopen("magic.in","r",stdin);
        //freopen("magic.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        int x,y,z;
        while(m--){
            scanf("%s",c);
            if(c[0]=='M'){
                scanf("%d%d%d",&x,&y,&z);
                for(int i=x;i<=y;i++)a[i]+=z;
            }
            if(c[0]=='A'){
                scanf("%d%d%d",&x,&y,&z);
                int cnt=0;
                for(int i=x;i<=y;i++)
                    if(a[i]>=z)cnt++;
                printf("%d
    ",cnt);
            }
        }
        return 0;
    }
    View Code

    Problem 4 吃豆豆(pacman.cpp/c/pas)

    【问题描述】

             两个PACMAN吃豆豆。一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方。PACMAN走到豆豆处就会吃掉它。PACMAN行走的路线很奇怪,只能向右走或者向上走,他们行走的路线不可以相交。

             请你帮这两个PACMAN计算一下,他们两加起来最多能吃掉多少豆豆。

    【输入文件】

             第一行为一个整数N,表示豆豆的数目。接下来N行,每行一对正整数Xi,Yi,表示第i个豆豆的坐标。任意两个豆豆的坐标都不会重合。

    【输出文件】

             仅有一行包含一个整数,即两个PACMAN加起来最多能吃掉的豆豆数量。

    【输入样例】

    8

    8  1

    1  5

    5  7

    2  2

    7  8

    4  6

    3  3

    6  4

    【输出样例】

    7

    【数据规模】

    对于30%的数据,1<=N<=25;

    对于70%的数据,1<=N<=500;

    对于100%的数据,1<=N<=2000,1<=Xi ,Yi <=200000  ;

     正解费用流 原因同上.

  • 相关阅读:
    Vue之computed与watch的使用
    Vue之组件的生命周期
    Vue之过滤器的使用
    Vue之父子组件的通信
    Vue之组件的使用
    Vue之数据绑定
    Vue之指令系统
    20182316胡泊 课程总结
    20182316胡泊 《数据结构与面向对象程序设计》实验9报告
    20182316胡泊 第10周学习总结
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5900022.html
Copyright © 2020-2023  润新知