zoukankan      html  css  js  c++  java
  • NOIP 2010题解

    唔..NOIP2010比较简单,总体感觉不错.

    Problem 1: 机器翻译

    水题,队列的简单应用.

    读入时判断是否在内存中,可以用hash优化.如果不在内存中push进内存,放不下了pop header不用说了.上代码(未hash优化)

    //Bazinga!
    #include "cstdio"
    int sum,i,m,n;
    struct Q{
        int len,head,tail,qub[1001],i;
        void push(int n){
            qub[tail]=n;
            ++tail;
            if(len==m){
                ++head;
            }else{
                ++len;
            }
        }
        void has(int n){
            for(i=head;i<tail;++i){
                if(qub[i]==n){
                    return;
                }
            }
            push(n);
            ++sum;
        }
    } q;
    int main(){
        scanf("%d%d",&m,&n);
        while(n--){
            scanf("%d",&i);
            q.has(i);
        }
        printf("%d", sum);
        return 0;
    }
    Click to see my ugly code.

    hash优化版(不加也没关系...加了纯属多耗内存,但是在大数据前肯定要快.)

    #include "cstdio"
    int sum,i,m,n;
    bool h[1001];
    struct Q{
        int len,head,tail,qub[1001],i;
        void push(int n){
            h[qub[tail]=n]=true;
            ++tail;
            if(len==m){
                h[qub[head]]=false;
                ++head;
            }else{
                ++len;
            }
        }
        void has(int n){
            if(h[n]) return;
            push(n);
            ++sum;
        }
    } q;
    int main(){
        scanf("%d%d",&m,&n);
        while(n--){
            scanf("%d",&i);
            q.has(i);
        }
        printf("%d", sum);
        return 0;
    }
    DON'T CLICK ME

    Problem 2: 乌龟棋

    非常经典的动态规划题目,不算难,但是对刚接触DP的人来说也不容易.

    设$f[i,j,k,l]$为1格卡~4格卡各使用了i~l张能获得的最高分,则动规方程为

    $f[i,j,k,l]=score[i+2j+3k+4l]+maxleft( f[i-1,j,k,l],f[i,j-1,k,l],f[i,j,k-1,l],f[i,j,k,l-1] ight)$

    边界条件$f[0,0,0,0]=score[0]$..

    上代码:

    //ug! So comfortable!
    #include "cstdio"
    int f[41][41][41][41],c[5],s[350],m,n,i,j,k,l;
    int t1,t2,t3,t4,t5;
    inline int mx(int a,int b){if(a>b){return a;}else{return b;}}
    int main(){
        scanf("%d%d",&n,&m);
        for(i=0;i<n;++i){
            scanf("%d",&s[i]);
        }
        for(i=0;i<m;++i){
            scanf("%d",&j);
            ++c[j];
        }
        t1=c[1];
        t2=c[2];
        t3=c[3];
        t4=c[4];
        for(i=0;i<=t1;++i){
            for(j=0;j<=t2;++j){
                for(k=0;k<=t3;++k){
                    for(l=0;l<=t4;++l){
                        t5=j+k+(l<<1);
                        t5<<=1;
                        if(i>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i-1][j][k][l]);
                        if(j>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i][j-1][k][l]);
                        if(k>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i][j][k-1][l]);
                        if(l>0) f[i][j][k][l]=mx(f[i][j][k][l],f[i][j][k][l-1]);
                        f[i][j][k][l]+=s[t5+i+k];
                    }
                }
            }
        }
        printf("%d", f[t1][t2][t3][t4]);
        return 0;
    }
    Don't touch me.

    Problem 3: 关押罪犯

    一道使用并查集的贪心算法题.输入所有怨气值,从大到小排序,一个个减小看有没有与现有的方案冲突;若冲突,输出当前怨气值,退出;不冲突,输出0.

    一般解法是利用二分图二分答案,这样的时间复杂度是$left( ext{It's really not clear. Depends on one's code.}\ ext{There are many ways to implement the algorithm}\ ext{and does not contains the same time complexity,}\ ext{pretty sorry but I can't help.} ight)$.这样的想法很明确,但是不好写,而且慢.

    用并查集写的,很短,很快,时间复杂度大约$ ext{O}left( alphaleft( n ight) m ight)$.

    顺便贴上我的代码:

    #include "cstdio"
    #include "algorithm"
    using namespace std;
    struct edge{
        int a,b,c;
        bool operator <(const edge x)const{
            return c>x.c;
        }
    } e[100010];
    int n,m,f[40020],x,y,t,p,i,j;
    int find(int x){
        t=x;
        p=x;
        //find root
        while(t=f[t],t!=x){
            x=t;
        }
        //path compressing
        while(f[p]=t,p=f[p],p!=t){};
        return t;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(i=0;i<m;++i){
            scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
        }
        t=n<<1;
        for(i=0;i<=t;++i){
            f[i]=i;
        }
        sort(e,e+m);
        for(i=0;i<m;++i){
            x=find(e[i].a);
            y=find(e[i].b);
            if(x==y){
                printf("%d", e[i].c);//largest
                return 0;
            }
            f[y]=find(e[i].a + n);
            f[x]=find(e[i].b + n);
        }
        printf("0");
        return 0;
    }
    There is nothing more I could tell you..All right, others' code encourages man.

     Problem 4: 引水入城

    这是一道非常综合的题目,分两个小题.

    1) 是否所有沙漠城市都有水供应. BFS即可
    2) 最少需要多少个湖泊城市建立抽水站

    而第 2) 小题仔细想又可以分为

    2.1) 求每个湖泊城市覆盖的沙漠城市范围
    2.2) 求如何用最少的线段覆盖整条线段

    第一个BFS可过,用一种类似DP的方法亦可(这种方法存在反例,但是数据比较弱,除了第一个测试数据跑不过以外全可,非常快).
    第二个贪心.

    $ ext{The final tip:}$

    $ ext{Be careful using DFS because of system stack overflow and it's performance loss.}color{orange}{ ext{YOU'VE BEEN WARNED}}$

    I TOLD YOU DONT LOOK AT THIS BUT YOU ARE NOT LISTENING!!!! 
    #include "cstdio"
    #include "algorithm"
    using namespace std;
    struct edge{
        int a,b,c;
        bool operator <(const edge x)const{
            return c>x.c;
        }
    } e[100010];
    int n,m,f[40020],x,y,t,p,i,j;
    int find(int x){
        t=x;
        p=x;
        //find root
        while(t=f[t],t!=x){
            x=t;
        }
        //path compressing
        while(f[p]=t,p=f[p],p!=t){};
        return t;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(i=0;i<m;++i){
            scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
        }
        t=n<<1;
        for(i=0;i<=t;++i){
            f[i]=i;
        }
        sort(e,e+m);
        for(i=0;i<m;++i){
            x=find(e[i].a);
            y=find(e[i].b);
            if(x==y){
                printf("%d", e[i].c);//largest
                return 0;
            }
            f[y]=find(e[i].a + n);
            f[x]=find(e[i].b + n);
        }
        printf("0");
        return 0;
    }
    Okay..It's wrong.
    #include "cstdio"
    #include "algorithm"
    #define max(a,b) (a>b?a:b)
    struct visitQueue
    {
        short x[250000],y[250000];
        int h,t;
    } vq;
    #define pushq(xa,ya) vq.x[vq.t]=xa,vq.y[vq.t]=ya,++vq.t;
    bool v[510][510];
    int i,j,k,l,m,n,t,s;
    int h[510][510],f[510][510];
    struct range{
        int s,e;
    } r[510];
    bool cmp(range a,range b){
        return a.s<b.s;
    }
    void bfs(int x,int y){
        if(v[x][y]) return;
        vq.h=0;
        vq.t=1;
        vq.x[0]=x;
        vq.y[0]=y;
        v[x][y]=true;
        while(vq.h!=vq.t){
            i=vq.x[vq.h];
            j=vq.y[vq.h];
            k=h[i][j];
            if(i>1&&h[i-1][j]<k&&(!v[i-1][j])){
                v[i-1][j]=true;
                pushq(i-1,j);
            }
            if(i<m&&h[i+1][j]<k&&(!v[i+1][j])){
                v[i+1][j]=true;
                pushq(i+1,j);
            }
            if(j>1&&h[i][j-1]<k&&(!v[i][j-1])){
                v[i][j-1]=true;
                pushq(i,j-1);
            }
            if(j<n&&h[i][j+1]<k&&(!v[i][j+1])){
                v[i][j+1]=true;
                pushq(i,j+1);
            }
            ++vq.h;
        }
    }
    int main(){
        scanf("%d%d",&m,&n);
        for(i=1;i<=m;++i){
            for(j=1;j<=n;++j){
                scanf("%d",&h[i][j]);
            }
        }
     ///////////
     //   if(m==2&&n==5&&h[2][3]==6&&h[1][5]==3){
     //       printf("1
    1");//a hack for the first testing data. Remove this block
     //       return 0;
     //   }
     ///////////
        for(l=1;l<=n;++l){
            bfs(1,l);
        }
        t=0;
        for(j=1;j<=n;++j){
            if(!v[m][j]) ++t;
        }
        if(t>0){
            printf("0
    %d",t);
            return 0;
        }
        printf("1
    ");
        for(j=1;j<=n;++j){
            if(h[m][j-1]<h[m][j] && j>1){
                f[m][j]=f[m][j-1];
            }else{
                f[m][j]=j;
            }
        }
        for(i=m-1;i>0;--i){
            for(j=1;j<=n;++j){
                f[i][j]=f[i+1][j];
                if(j>1 && h[i][j-1]<h[i][j] && f[i][j-1]<f[i][j]){
                    f[i][j]=f[i][j-1];
                }
            }
        }
        for(j=1;j<=n;++j){
            r[j].s=f[1][j];
        }
        for(j=n;j>0;--j){
            if(h[m][j+1]<h[m][j]&&j<n){
                f[m][j]=f[m][j+1];
            }else{
                f[m][j]=j;
            }
        }
        for(i=m-1;i>0;--i){
            for(j=n;j>0;--j){
                f[i][j]=f[i+1][j];
                if(j<n&&h[i][j+1]<h[i][j]&&f[i][j+1]>f[i][j]){
                    f[i][j]=f[i][j+1];
                }
            }
        }
        for(j=1;j<=n;++j){
            r[j].e=f[1][j];
        }
        std::sort(r,r+n,cmp);
        l=0;
        i=0;
        s=0;
        while(i<=n && s<n){
            if(r[i].s <= s+1){
                ++l;
                k=1;
                while(i<=n && r[i].s<=s+1){
                    if(r[i].e>k){
                        k=r[i].e;
                    }
                    ++i;
                }
                s=k;
            }
        }
        printf("%d",l);
        return 0;
    }
    The code is this, exactly.
  • 相关阅读:
    EasyNVR RTSP转RTMPHLS流媒体服务器前端构建之:使用BootstrapPagination以分页形式展示数据信息
    EasyNVR H5无插件直播方案前端构建之:videojs初始化的一些样式处理
    EasyNVR H5无插件直播方案前端构建之:如何播放HLS
    EasyNVR RTSP转RTMP/HLS流媒体服务器前端构建之:bootstrap弹窗功能的实现
    EasyNVR H5无插件直播方案前端构建之:如何区分PC端和移动端
    EasyNVR RTSP转RTMPHLS流媒体服务器前端构建之:通过接口获取实时信息
    实现RTSP摄像机进行网页直播和微信直播的技术方案
    EasyNVR RTSP转RTMPHLS流媒体服务器前端构建之:bootstrapdatepicker日历插件的实时动态展现
    EasyNVR H5无插件直播方案前端构建之:播放界面添加实时云台控制界面
    EasyNVR H5无插件直播方案前端构建之:实时直播的四分屏的前端展示
  • 原文地址:https://www.cnblogs.com/tmzbot/p/3886969.html
Copyright © 2011-2022 走看看