NOIP模拟9.28

2013提高D2
A.积木大赛(模拟+递归+st表)AC
B.花匠(贪心)AC
C.华容道(bfs+spfa)40.搜索手残写挂,本来有70分的。
C正解是:因为图是不变的,有很多询问,所以我们考虑预处理。记空白格为白块,目标块为黑块,目标位置为目标位置。
考虑到我们关心的状态只是白块和黑块的位置,而只有白块在黑块周围时,黑块的位置才会改变,因此我们用状态x,y,k表示黑块在(x,y),白块在黑块的k方向上。(k=0,1,2,3,分别对应下,上,右,左)我们考虑转移,以黑块的位置改变作为一次转移。例如黑块位置为(x,y),我们想要把它移动到位置(x+1,y),则我们要先把白块移到(x+1,y),假设这需要w步,然后再用一步交换黑块和白块的位置,使得白块到达(x+1,y),而黑块到达(x,y)。一共需要走(w+1)步,我们发现这样转移的话,黑块一定总是在白块周围,因此我们可以这样建图:
1.(x,y,k)->(xx,yy,re(k)),边权为1,表示黑白块交换位置(re[k]就是k的反方向)
2.(x,y,k)->(x,y,kk),边权用bfs算一下即可,表示黑块从白块的k方向,移动到白块的kk方向所需的步数。
然后对于每一个询问,我们先把白块移动到黑块周围,最多四种可能,分别用bfs算出步数,放入队列,然后跑spfa即可。

A

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,a[N],st[N][20],Log[N];
ll ans=0;
inline int rmq(int x,int y){
    int t=Log[y-x+1];
    return min(st[x][t],st[y-(1<<t)+1][t]);
}
void solve(int st,int ed,int val){
    if(st>ed) return;
    int x=rmq(st,ed),l=st;ans+=x-val;
    while(l<=ed&&a[l]==x) l++;
    for(int i=l+1;i<=ed;++i){
        if(a[i]==x){
            solve(l,i-1,x);l=i+1;while(l<=ed&&a[l]==x) l++;i=l;
        }
    }solve(l,ed,x);
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();Log[0]=-1;
    for(int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;
    for(int i=1;i<=n;++i) a[i]=read(),st[i][0]=a[i];
    for(int i=1;i<=Log[n];++i)
        for(int j=1;j<=n;++j)
            if(j+(1<<i-1)<=n) st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);
    int l=1;while(l<=n&&a[l]==0) l++;
    for(int i=l+1;i<=n;++i){
        if(a[i]==0){
            solve(l,i-1,0);l=i+1;while(l<=n&&a[l]==0) l++;i=l;
        }
    }solve(l,n,0);
    printf("%d\n",ans);
    return 0;
}

B

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,a[N],num=0,ans=0;
int main(){
//  freopen("a.in","r",stdin);
    n=read();a[++num]=read();
    for(int i=2;i<=n;++i){
        int x=read();if(x!=a[num]) a[++num]=x; 
    }
    if(num==1){puts("1");return 0;}
    for(int i=2;i<=num-1;++i){
        if(a[i]<a[i-1]&&a[i]<a[i+1]) ans++;
        if(a[i]>a[i-1]&&a[i]>a[i+1]) ans++;
    }
    printf("%d\n",ans+2);
    return 0;
}

C

70分bfs

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 32
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m,qu,ex,ey,sx,sy,tx,ty,ans=0,dx[]={1,-1,0,0},dy[]={0,0,1,-1};
bool mp[N][N],f[N][N][N][N];
struct node{
    int ex,ey,sx,sy,k;
    node(int _ex,int _ey,int _sx,int _sy,int _k){
        ex=_ex;ey=_ey;sx=_sx;sy=_sy;k=_k;
    }
};
int bfs(){
    queue<node>q;
    node tmp(ex,ey,sx,sy,0);q.push(tmp);f[ex][ey][sx][sy]=1;
    while(!q.empty()){
        node x=q.front();q.pop();
        if(x.ex==tx&&x.ey==ty){
            for(int i=0;i<4;++i)
                if(x.sx+dx[i]==tx&&x.sy+dy[i]==ty) return x.k+1; 
        }
        for(int i=0;i<4;++i){
            int xx=x.ex+dx[i],yy=x.ey+dy[i];
            if(xx<1||xx>n||yy<1||yy>m||!mp[xx][yy]) continue;
            if(xx==x.sx&&yy==x.sy){
                if(!f[xx][yy][x.ex][x.ey]){
                    f[xx][yy][x.ex][x.ey]=1;
                    node y(xx,yy,x.ex,x.ey,x.k+1);q.push(y);
                }
            }
            else if(!f[xx][yy][x.sx][x.sy]){
                f[xx][yy][x.sx][x.sy]=1;
                node y(xx,yy,x.sx,x.sy,x.k+1);q.push(y);
            }
        }
    }
    return -1;
}
int main(){
//  freopen("puzzle13.in","r",stdin);
//  freopen("a.out","w",stdout);
    n=read();m=read();qu=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) mp[i][j]=read();
    while(qu--){
        ex=read(),ey=read(),sx=read(),sy=read();tx=read(),ty=read();
        if(sx==tx&&sy==ty){puts("0");continue;}
        memset(f,0,sizeof(f));
        printf("%d\n",bfs());
    }
    return 0;
}

满分bfs+spfa

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define pa pair<pair<int,int>,int>
#define N 32
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m,qu,dx[]={1,-1,0,0},dy[]={0,0,1,-1},h[N][N][4],num=0,d[N][N][4];
bool mp[N][N],f[N][N],inq[N][N][4];
struct edge{
    pa to;int next,val;
}data[N*N*10];
inline void add(int x,int y,int k,pa xx,int val){
    data[++num].to=xx;data[num].next=h[x][y][k];h[x][y][k]=num;data[num].val=val;
}
inline int re(int k){
    if(k==0||k==2) return k+1;else return k-1;
}
int bfs(int sx,int sy,int tx,int ty){
    memset(f,0,sizeof(f));
    queue<pa>q;q.push(make_pair(make_pair(sx,sy),0));f[sx][sy]=1;
    while(!q.empty()){
        int x=q.front().first.first,y=q.front().first.second;
        int step=q.front().second;q.pop();
        if(x==tx&&y==ty) return step;
        for(int i=0;i<4;++i){
            int xx=x+dx[i],yy=y+dy[i];
            if(xx<1||xx>n||yy<1||yy>m||!mp[xx][yy]) continue;
            if(!f[xx][yy]) q.push(make_pair(make_pair(xx,yy),step+1)),f[xx][yy]=1;
        }
    }return inf;
}
void spfa(int ex,int ey,int sx,int sy,int tx,int ty){
    if(sx==tx&&sy==ty){puts("0");return;}
    queue<pa>q;memset(d,0x3f,sizeof(d));mp[sx][sy]=0;
    for(int i=0;i<4;++i){
        int x=sx+dx[i],y=sy+dy[i];
        if(x<1||x>n||y<1||y>m||!mp[x][y]) continue;
        d[sx][sy][i]=bfs(ex,ey,x,y);
        if(d[sx][sy][i]==inf) continue;
        q.push(make_pair(make_pair(sx,sy),i));inq[sx][sy][i]=1;
    }mp[sx][sy]=1;
    while(!q.empty()){
        int x=q.front().first.first,y=q.front().first.second;
        int k=q.front().second;q.pop();inq[x][y][k]=0;
        for(int i=h[x][y][k];i;i=data[i].next){
            pa yy=data[i].to;
            if(d[yy.first.first][yy.first.second][yy.second]>d[x][y][k]+data[i].val){
                d[yy.first.first][yy.first.second][yy.second]=d[x][y][k]+data[i].val;
                if(!inq[yy.first.first][yy.first.second][yy.second]){
                    inq[yy.first.first][yy.first.second][yy.second]=1;q.push(yy);
                }
            }
        }
    }
    int ans=inf;
    for(int i=0;i<4;++i)
        ans=min(ans,d[tx][ty][i]);
    if(ans==inf) puts("-1");
    else printf("%d\n",ans);
}
int main(){
//  freopen("puzzle7.in","r",stdin);
    n=read();m=read();qu=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) mp[i][j]=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            if(!mp[i][j]) continue;mp[i][j]=0;
            for(int k=0;k<4;++k){
                int x=i+dx[k],y=j+dy[k];
                if(x<1||x>n||y<1||y>m||!mp[x][y]) continue;
                add(i,j,k,make_pair(make_pair(x,y),re(k)),1);
                for(int kk=0;kk<4;++kk){
                    if(kk<=k) continue;
                    int xx=i+dx[kk],yy=j+dy[kk];
                    if(xx<1||xx>n||yy<1||yy>m||!mp[xx][yy]) continue;
                    int val=bfs(x,y,xx,yy);
                    add(i,j,k,make_pair(make_pair(i,j),kk),val);
                    add(i,j,kk,make_pair(make_pair(i,j),k),val);
                }
            }mp[i][j]=1;
        }
    while(qu--){
        int ex=read(),ey=read(),sx=read(),sy=read(),tx=read(),ty=read();
        spfa(ex,ey,sx,sy,tx,ty);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值