• NOIP2017 棋盘


    题目传送门(洛咕)

    题目描述

    有一个m×m的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。

    任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的), 你只能向上、 下、左、 右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费1个金币。

    另外, 你可以花费2个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用, 而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法; 只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。

    现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?

    输入格式

    第一行包含两个正整数m, n以一个空格分开,分别代表棋盘的大小,棋盘上有颜色的格子的数量。

    接下来的nn行,每行三个正整数x, y, c,分别表示坐标为(x,y)的格子有颜色c。

    其中c=1代表黄色,c=0代表红色。 相邻两个数之间用一个空格隔开。 棋盘左上角的坐标为(1,1),右下角的坐标为(m,m)。

    棋盘上其余的格子都是无色。保证棋盘的左上角,也就是(1,1) 一定是有颜色的。

    输出格式

    一个整数,表示花费的金币的最小值,如果无法到达,输出-1

    输入输出样例

    输入 #1
    5 7
    1 1 0
    1 2 0
    2 2 1
    3 3 1
    3 4 0
    4 4 1
    5 5 0
    输出 #1
    8
    输入 #2
    5 5
    1 1 0
    1 2 0
    2 2 1
    3 3 1
    5 5 0
    输出 #2
    -1
     这道题算是进年来PJT3较为简单的一道,但也有很多需要注意的地方:
    1.魔法只会用在空地上(显然用不着改变非同色地形)
    2.用book记录会T
    3.并不是只可以向右下走
    这道题一上来我选的深搜(不知道为什么。。。
    没有记忆,用了book,爆T55分
    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    int a[105][105];
    int ans=999999999;
    int n,m;
    int xb=0;
    int book[105][105];
    inline int read()
    {
        int x=0,f=1; char c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=0; c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
        return f?x:-x;
    }
    void dfs(int x,int y,int flag,int cnt,int col)
    {
        if(x==n&&y==n)
        {
            xb=1;
            ans=min(ans,cnt);
            return;
        }
        if(book[x][y+1]==0)
        {
            book[x][y+1]=1;
            if(col==a[x][y+1]) dfs(x,y+1,0,cnt,a[x][y+1]);
            else if(col!=a[x][y+1]&&a[x][y+1]!=0) dfs(x,y+1,0,cnt+1,a[x][y+1]);
            else if(a[x][y+1]==0&&flag==0) dfs(x,y+1,1,cnt+2,a[x][y]);
            book[x][y+1]=0;
        }
        if(book[x+1][y]==0)
        {
            book[x+1][y]=1;
            if(col==a[x+1][y]) dfs(x+1,y,0,cnt,a[x+1][y]);
            else if(col!=a[x+1][y]&&a[x+1][y]!=0) dfs(x+1,y,0,cnt+1,a[x+1][y]);
            else if(a[x+1][y]==0&&flag==0) dfs(x+1,y,1,cnt+2,a[x][y]);
            book[x+1][y]=0;
        }
        if(book[x][y-1]==0)
        {
            book[x][y-1]=1;
            if(col==a[x][y-1]) dfs(x,y-1,0,cnt,a[x][y-1]);
            else if(col!=a[x][y-1]&&a[x][y-1]!=0) dfs(x,y-1,0,cnt+1,a[x][y-1]);
            else if(a[x][y-1]==0&&flag==0) dfs(x,y-1,1,cnt+2,a[x][y]);
            book[x][y-1]=0;
        }
        if(book[x-1][y]==0)
        {
            book[x-1][y]=1;
            if(col==a[x-1][y]) dfs(x-1,y,0,cnt,a[x-1][y]);
            else if(col!=a[x-1][y]&&a[x-1][y]!=0) dfs(x-1,y,0,cnt+1,a[x-1][y]);
            else if(a[x-1][y]==0&&flag==0) dfs(x-1,y,1,cnt+2,a[x][y]);
            book[x-1][y]=0;
        }
    }
    int main()
    {
        memset(book,-1,sizeof(book));
        int x,y,z;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                book[i][j]=0;
        for(int i=1;i<=m;i++)
        {
            x=read(); y=read(); z=read();
            a[x][y]=z+1;
        }
        dfs(1,1,0,0,a[1][1]);
        if(xb==1) cout<<ans;
        else cout<<-1;
        return 0;
    }

    后来加了记录最优情况的剪枝,A了

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    int a[105][105];
    int ans=999999999;
    int n,m;
    int xb=0;
    int js[105][105];
    int book[105][105];
    inline int read()
    {
        int x=0,f=1; char c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=0; c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
        return f?x:-x;
    }
    void dfs(int x,int y,int flag,int cnt,int col)
    {
        if(js[x][y]<=cnt) return;
        js[x][y]=min(js[x][y],cnt);
        if(x==n&&y==n)
        {
            xb=1;
            ans=min(ans,cnt);
            return;
        }
        if(book[x][y+1]==0)
        {
            if(col==a[x][y+1]) dfs(x,y+1,0,cnt,a[x][y+1]);
            else if(col!=a[x][y+1]&&a[x][y+1]!=0) dfs(x,y+1,0,cnt+1,a[x][y+1]);
            else if(a[x][y+1]==0&&flag==0) dfs(x,y+1,1,cnt+2,a[x][y]);
        }
        if(book[x+1][y]==0)
        {
            if(col==a[x+1][y]) dfs(x+1,y,0,cnt,a[x+1][y]);
            else if(col!=a[x+1][y]&&a[x+1][y]!=0) dfs(x+1,y,0,cnt+1,a[x+1][y]);
            else if(a[x+1][y]==0&&flag==0) dfs(x+1,y,1,cnt+2,a[x][y]);
        }
        if(book[x][y-1]==0)
        {
            if(col==a[x][y-1]) dfs(x,y-1,0,cnt,a[x][y-1]);
            else if(col!=a[x][y-1]&&a[x][y-1]!=0) dfs(x,y-1,0,cnt+1,a[x][y-1]);
            else if(a[x][y-1]==0&&flag==0) dfs(x,y-1,1,cnt+2,a[x][y]);
        }
        if(book[x-1][y]==0)
        {
            if(col==a[x-1][y]) dfs(x-1,y,0,cnt,a[x-1][y]);
            else if(col!=a[x-1][y]&&a[x-1][y]!=0) dfs(x-1,y,0,cnt+1,a[x-1][y]);
            else if(a[x-1][y]==0&&flag==0) dfs(x-1,y,1,cnt+2,a[x][y]);
        }
    }
    int main()
    {
        memset(book,-1,sizeof(book));
        memset(js,127,sizeof(js));
        int x,y,z;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                book[i][j]=0;
        for(int i=1;i<=m;i++)
        {
            x=read(); y=read(); z=read();
            a[x][y]=z+1;
        }
        dfs(1,1,0,0,a[1][1]);
        if(xb==1) cout<<ans;
        else cout<<-1;
        return 0;
    }

  • 相关阅读:
    gcc和g++的区别
    configure svn server on win
    FD_SET,FD_ISSET,FD_ZERO,select
    intel中的cr寄存器
    Linux系统环境下的Socket编程详细解析
    可重入函数与不可重入函数
    初步认识迭代服务器和并发服务器
    排序
    fd_set 用法
    MFC消息映射
  • 原文地址:https://www.cnblogs.com/ssf-xiaoban/p/11544669.html
Copyright © 2020-2023  润新知