zoukankan      html  css  js  c++  java
  • NOIP2013 DAY2题解

    DAY2 

    T1积木大赛

    传送门

    题目大意:每次可以选区间[l,r]加1,最少选几次,让每个位置有

    它应有的高度。

    题解:O(n)扫一遍就好了。后一个比前一个的高度低,那么前一个已经把它覆盖了,

    如果高那么就需要+1了。

    代码:

    #include<iostream>
    #include<cstdio>
    #define maxn 100009
    using namespace std;
    
    int n,x,pre,ans;
    
    void read(int &x){
        char ch=getchar();int f=1;x=0;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        x*=f;
    }
    
    int main(){
        freopen("block.in","r",stdin);
        freopen("block.out","w",stdout);
        read(n);
        for(int i=1;i<=n;i++){
            read(x);
            if(x>pre)ans=ans+x-pre;
            pre=x;
        }
        printf("%d
    ",ans);
        fclose(stdin);fclose(stdout);
        return 0;
    }
    AC

    T2花匠

    传送门

    题目大意:求最长波动子序列

    题解:贪心

    暴力dp[i][1/0][1/0]表示到第i个数作为波峰(1)或波谷(0)选(1)还是不选(0)的最长长度

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100008
    using namespace std;
    
    int n,h[maxn],dp[maxn][2][2];
    
    void read(int &x){
        char ch=getchar();x=0;int f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        x=x*f;
    }
    
    int main(){
        read(n);
        for(int i=1;i<=n;i++)read(h[i]);
        dp[1][1][1]=dp[1][0][1]=1;
        for(int i=2;i<=n;i++){
            for(int j=1;j<i;j++){
                if(h[i]>h[j])dp[i][1][1]=max(dp[i][1][1],dp[j][0][1]+1);
                if(h[i]<h[j])dp[i][0][1]=max(dp[i][0][1],dp[j][1][1]+1);
                dp[i][0][0]=dp[i][1][0]=max(max(dp[j][0][1],dp[j][0][0]),max(dp[j][1][0],dp[j][1][1]));
            }
        }
        printf("%d
    ",max(max(dp[n][1][1],dp[n][1][0]),max(dp[n][0][1],dp[n][0][0])));
        return 0;
    }
    70

    这不跟昨天湖南的题一样么。

    对于 5 4 3 2 9

    5 2 9,4 2 9,3 2 9,好像没什么区别。那么连续递减的5 4 3 2就可以看成一个数了。

    以一个数为大的和小的分别扫一遍就好。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100008
    using namespace std;
    
    int ans,ret,cur,flag,n,h[maxn];
    
    void read(int &x){
        char ch=getchar();x=0;int f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        x=x*f;
    }
    
    int main(){
        freopen("flower.in","r",stdin);
        freopen("flower.out","w",stdout);
        read(n);
        for(int i=1;i<=n;i++)read(h[i]);
        cur=h[1];ans=1;
        for(int i=2;i<=n;i++){
            if(flag){
                if(h[i]<cur)flag=0,ans++,cur=h[i];
                else cur=max(cur,h[i]);
            }else{
                if(h[i]>cur)flag=1,ans++,cur=h[i];
                else cur=min(cur,h[i]);
            }
        }
        cur=h[1];ret=1;flag=0;
        for(int i=2;i<=n;i++){
            if(flag){
                if(h[i]>cur)flag=0,ret++,cur=h[i];
                else cur=min(cur,h[i]);
            }else{
                if(h[i]<cur)flag=1,ret++,cur=h[i];
                else cur=max(cur,h[i]);
            }
        }
        ans=max(ans,ret);
        printf("%d
    ",ans);
        fclose(stdin);fclose(stdout);
        return 0;
    }
    AC

    一个多月前我做的...似乎是看了就是看了题解...

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,pre,now,r=1,d=1;
    int main()
    {
        scanf("%d",&n);
        scanf("%d",&pre);//当前这盆花前面那盆花的高度,初始为第一盆花的高度。 
        for(int i=1;i<n;i++)
        {
            scanf("%d",&now);
            if(now>pre)r=max(r,d+1);//当前这盆花高度大于前面那盆花高度 
            if(now<pre)d=max(d,r+1);//说明现在是上升序列,就要求出到Now这个花盆且波动为 
            pre=now;             //上升的最优解,就从原来求出的最后波动为上升的最优解,
        }                       //(也就是说此时当前这盆花不加入之前最优解,移走)
        printf("%d",max(r,d));//和从最后波动为下降的最优解+1选取最优值(不移走)。
        return 0;
    }
    AC

    T3华容道

    传送门

    题目大意:一个n*m的矩阵,有n*m-1个棋子。1表示该棋子能移动,0表示不能。

    给出指定位置和目标位置。求最少几步能利用空白格子将指定位置棋子移到目标位置。

    题解:

    dfs 5分...怀疑人生

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define inf 100000000
    using namespace std;
    
    int n,m,q,x,cnt,ans;
    int ex,ey,sx,sy,tx,ty;
    int t[40][40],tmp[40][40],vis[40][40];
    int mx[4]={0,1,-1,0},
        my[4]={-1,0,0,1};
    
    void read(int &x){
        char ch=getchar();x=0;int f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        x=x*f;
    }
    
    void dfs(int ex,int ey,int sx,int sy,int tx,int ty,int prex,int prey,int ste){
        if(ex==tx&&ey==ty&&abs(sx-ex)+abs(sy-ey)<=1){
            ans=min(ans,ste+1);
            return;
        }
        for(int i=0;i<4;i++){
            int xx=ex+mx[i],yy=ey+my[i];
            if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&t[xx][yy]&&(xx!=prex||yy!=prey)&&!vis[xx][yy]){
                vis[xx][yy]=true;
                if(xx==sx&&yy==sy){
                    dfs(xx,yy,ex,ey,tx,ty,ex,ey,ste+1);
                }else dfs(xx,yy,sx,sy,tx,ty,ex,ey,ste+1);
            }
        }
    }
    
    int main(){
    //    freopen("puzzle.in","r",stdin);
    //    freopen("puzzle.out","w",stdout);
        read(n);read(m);read(q);
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          read(t[i][j]);
        for(int i=1;i<=q;i++){
            cnt=0;ans=inf;
            memset(vis,0,sizeof(vis));
            read(ex);read(ey);//空白格子 
            vis[ex][ey]=true;
            read(sx);read(sy);//指定棋子 
            read(tx);read(ty);//目标位置
            if(sx==tx&&sy==ty){
                printf("0
    ");
                continue;
            }
            dfs(ex,ey,sx,sy,tx,ty,0,0,0); 
            if(ans==inf)printf("-1
    ");
            else printf("%d
    ",ans);
        }
    //    fclose(stdin);fclose(stdout);
        return 0;
    }
    5

    bfs 70 其实考试时开始写的bfs。发现不会记录状态。

    看了题解算来只需要记录空白格子和指定棋子的位置就好了。

    时间复杂度O(q*(nm)^2)

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    
    int ans,n,m,qx,tx,ty;
    int t[40][40],vis[40][40][40][40];
    int mx[4]={0,1,0,-1},
        my[4]={-1,0,1,0};
    struct Node{
        int ex,ey,sx,sy,ste;
    }now;
    queue<Node>q;
    
    void read(int &x){
        char ch=getchar();x=0;int f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        x=x*f;
    }
    
    void BFS(){
        memset(vis,0,sizeof(vis));
        Node tmp,cur;
        vis[now.sx][now.sy][now.ex][now.ey]=true;
        while(!q.empty())q.pop();q.push(now);
        while(!q.empty()){
            cur=q.front();q.pop();
            if(cur.sx==tx&&cur.sy==ty){
                ans=cur.ste;
                return;
            }
            for(int i=0;i<4;i++){
                tmp=cur;
                int xx=tmp.ex+mx[i],yy=tmp.ey+my[i];
                if(!t[xx][yy]||xx<1||xx>n||yy<1||yy>m)continue;
                if(xx==tmp.sx&&yy==tmp.sy)tmp.sx=tmp.ex,tmp.sy=tmp.ey;
                tmp.ex=xx;tmp.ey=yy;tmp.ste=cur.ste+1;
                if(!vis[tmp.sx][tmp.sy][tmp.ex][tmp.ey]){
                    vis[tmp.sx][tmp.sy][tmp.ex][tmp.ey]=true;
                    q.push(tmp);
                }
            }
        }
    }
    
    int main(){
        read(n);read(m);read(qx);
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) read(t[i][j]);
        for(;qx;qx--){
            read(now.ex);read(now.ey);read(now.sx);read(now.sy);read(tx);read(ty);
            now.ste=0;ans=n*m;
            BFS();
            if(ans!=n*m)printf("%d
    ",ans);
            else printf("-1
    ");
        }
        return 0;
    }
    70

    正解..搜索+最短路。傻逼错误毁我青春...从下午写到现在...

    我还是单独开个随笔讲这个题吧。邪王真眼

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define maxn 5000
    #define inf 2147483647
    
    int n,m,qx,sumedge,ans,ex,ey,sx,sy,tx,ty,p;
    int map[40][40],pre_dis[40][40],head[maxn],vis[maxn],dis[maxn];
    int mx[4]={-1,0,1,0},
        my[4]={0,1,0,-1};
    struct Node{
        int x,y;
    }cur,nxt;
    queue<Node>q;
    queue<int>qn;
    
    struct Edge{
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[maxn];
    
    void add(int x,int y,int z){
        edge[++sumedge]=Edge(x,y,z,head[x]);
        head[x]=sumedge;
    }
    
    int get_id(int i,int j){
        return (i-1)*m*4+(j-1)*4;
    }
    
    void bfs(int ex,int ey,int sx,int sy,int d){
        memset(pre_dis,-1,sizeof(pre_dis));
        pre_dis[ex][ey]=0;pre_dis[sx][sy]=1;
        Node now,nxt;now.x=ex;now.y=ey;
        while(!q.empty())q.pop();
        q.push(now);
        while(!q.empty()){
            now=q.front();q.pop();
            int x=now.x,y=now.y;
            for(int i=0;i<4;i++){
                int xx=x+mx[i],yy=y+my[i];
                if(xx<1||xx>n||yy<1||yy>m||!map[xx][yy]||pre_dis[xx][yy]!=-1)continue;
                pre_dis[xx][yy]=pre_dis[x][y]+1;
                nxt.x=xx;nxt.y=yy;
                q.push(nxt);    
            }
        }
        if(d==4)return;
        int id=get_id(sx,sy);
        for(int i=0;i<4;i++)
         if(pre_dis[sx+mx[i]][sy+my[i]]>0)
           add(id+d,id+i,pre_dis[sx+mx[i]][sy+my[i]]);
        add(id+d,get_id(ex,ey)+(d+2)%4,1);
    }
    
    void spfa(int sx,int sy){
        memset(dis,-1,sizeof(dis));
        memset(vis,0,sizeof(vis));
        while(!qn.empty())qn.pop();
        int id=get_id(sx,sy);
        for(int i=0;i<4;i++)
            if(pre_dis[sx+mx[i]][sy+my[i]]!=-1){
                dis[id+i]=pre_dis[sx+mx[i]][sy+my[i]];
                qn.push(id+i);
            } 
        while(!qn.empty()){
            int cur=qn.front();qn.pop();vis[cur]=false;
            for(int i=head[cur];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(dis[v]>dis[cur]+edge[i].z||dis[v]==-1){
                    dis[v]=dis[cur]+edge[i].z;
                    if(!vis[v]){
                        vis[v]=true;
                        qn.push(v);
                    }
                }
            }
        }
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&qx);
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          scanf("%d",&map[i][j]);
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          if(map[i][j]){
              if(map[i-1][j])bfs(i-1,j,i,j,0);
              if(map[i][j+1])bfs(i,j+1,i,j,1);
              if(map[i+1][j])bfs(i+1,j,i,j,2);
              if(map[i][j-1])bfs(i,j-1,i,j,3);
          }
        for(int i=1;i<=qx;i++){
            scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
            if(sx==tx&&sy==ty){
                printf("0
    ");
                continue;
            }
            bfs(ex,ey,sx,sy,4);
            ans=inf;
            spfa(sx,sy);
            int id=get_id(tx,ty);
            for(int j=0;j<4;j++)
             if(dis[id+j]!=-1)ans=min(ans,dis[id+j]);
            if(ans==inf) ans=-1;
            printf("%d
    ",ans);
        }
        return 0;
    }
    AC
  • 相关阅读:
    在Fedora10上安装MySQL5.0.18,告捷!
    直接修改class文件内容即使是文本会导致App异常,正确方式是修改java再用生成的class替换掉原有的class
    生命的真谛不在于你呼吸的次数,而在于那些令你无法呼吸的时刻
    开放Fedora10自带的MySQL5.0.67的对外数据库服务
    重装上了Fedora8自带的MySQL5.0.45,再试,告捷!!
    Shell程序荟萃
    程序的价值
    两条Find指令
    Linux防火墙配置
    在Foreda8上安装libaio-0.3.105-2.i386.rpm
  • 原文地址:https://www.cnblogs.com/zzyh/p/7686050.html
Copyright © 2011-2022 走看看