2017年NOIP普及组第三题“chess”题解

2017年NOIP普及组第三题“chess”题解

作者:岸芷汀兰

题目:

链接:洛谷原题

思路:

很遗憾,这道题我没能在考场中写出来,在这里,向我的教练及朋友道歉,我让你们失望了。(QAQ)


50分:普通的dfs。
80分:普通的bfs。
100分:记忆化搜索。
那么记忆化搜索有什么用呢?当前答案大于当前节点的最小花费时,continue。所以要记录每个节点的最小花费。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
typedef long long ll;

using namespace std;
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=10*x+ch-'0';ch=getchar();}
     return x*f;
}

const int maxn=105,inf=999999999;
int n,m,a[maxn][maxn],ans=inf,now,dx[]={1,0,-1,0},dy[]={0,1};
int dist[maxn][maxn];
bool vis[maxn][maxn],viss[maxn][maxn];

inline bool check(int x,int y){
    if(x<1||x>n||y<1||y>n||viss[x][y])return false;
    return true;
}

inline void dfs(int x,int y){
    if(now>ans){
        return;
    }
    if(x==n&&y==n){
        if(ans>now)ans=now;
        return;
    }
    for(int i=0;i<4;i++){
        int tx=x+dx[i],ty=y+dy[i];
        if(!check(tx,ty))continue;
        if(vis[x][y]){//当前有颜色 
            if(vis[tx][ty]){//下一个有颜色 
                if(a[x][y]==a[tx][ty]&&now<dist[tx][ty]){
                    viss[tx][ty]=true;
                    dist[tx][ty]=now;
                    dfs(tx,ty);
                    viss[tx][ty]=false;
                }
                else if(a[x][y]!=a[tx][ty]&&now+1<dist[tx][ty]){
                    viss[tx][ty]=true;
                    dist[tx][ty]=now+1;
                    now++;
                    dfs(tx,ty);
                    now--;
                    viss[tx][ty]=false;
                }
            }
            else if(now+2<dist[tx][ty]&&(!vis[tx][ty])){//下一个无颜色 
                a[tx][ty]=a[x][y];
                viss[tx][ty]=true;
                dist[tx][ty]=now+2;
                now+=2;
                dfs(tx,ty);
                now-=2;
                viss[tx][ty]=false;
                a[tx][ty]=-1;
            }
        }
        else{//当前无颜色 
            if(vis[tx][ty]&&(now<dist[tx][ty])){
                if(a[tx][ty]==a[x][y]){
                    int temp=a[x][y];

                    a[x][y]=-1;
                    viss[tx][ty]=true;
                    dist[tx][ty]=now;
                    dfs(tx,ty);
                    viss[tx][ty]=false;
                    a[x][y]=temp;
                }
                else if((a[tx][ty]!=a[x][y])&&(now+1<dist[tx][ty])){
                    int temp=a[x][y];

                    a[x][y]=-1;
                    viss[tx][ty]=true;
                    dist[tx][ty]=now+1;
                    now++;
                    dfs(tx,ty);
                    now--;
                    viss[tx][ty]=false;
                    a[x][y]=temp;
                }
            }
            else if(!vis[tx][ty]){
                continue;
            }
        }
    }
    return;
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    memset(a,-1,sizeof(a));
    n=read();m=read();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            dist[i][j]=inf;
        }
    }
    for(int i=1;i<=m;i++){
        int x=read(),y=read(),z=read();
        a[x][y]=z;
        vis[x][y]=true;

    }
    dfs(1,1);
    if(ans==inf)printf("-1");
    else printf("%d",ans);
    return 0;
}

最后,向陪伴我的每一个老师、朋友道一声:“谢谢你们!”尽管这次没能拿回省一。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值