传送门:Problem P3956

https://www.cnblogs.com/violet-acmer/p/9827010.html

题解:

  BFS

  相关变量解释:

    color[maxn][maxn];...................................color[ i ][ j ] : ( i , j )点的颜色,-1代表无色
    dp[maxn][maxn];.......................................dp[ i ][ j ] : 从( 1 , 1 )点到( i , j )点需要花费的最少金币
    magic[maxn][maxn];..................................magic[ i ][ j ] : 判断 ( i , j )点是否使用魔法
    in[maxn][maxn];.........................................in[ i ][ j ] : 判断( i , j )点是否在队列中

  具体步骤:

    初始,将(1,1)点加入队列中;

    (1):保存队头元素并弹出

    (2):每次,判断当前点的上下左右点是否可以通过当前点使dp[ ][ ]变小,如果可以,更新dp[ ][ ],如果被更新的点不在队列中,加入队列

    (3):重复(2)过程,直到队列为空

AC代码:

 #include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
#define P pair<int ,int >
#define mem(a,b) memset(a,b,sizeof a)
const int maxn=+; int m,n;
int color[maxn][maxn];
int dp[maxn][maxn];
bool marge[maxn][maxn];
bool in[maxn][maxn];
queue<P >myqueue;
int dx[]={-,,,};
int dy[]={,,-,};
bool isSat(int val)
{
return val >= &&val <= m;
}
void Solve()
{
dp[][]=;//初始化dp[1][1],并将其加入到队列中
myqueue.push(P(,));
while(!myqueue.empty())//步骤(3)
{
P p=myqueue.front();//步骤(1)
myqueue.pop();
in[p.first][p.second]=false;
for(int i=;i < ;++i)//步骤(2)
{
int x=p.first+dx[i];
int y=p.second+dy[i];
if(isSat(x) && isSat(y))
{
if(!marge[p.first][p.second])//如果当前点的未使用过魔法的,也就意味这当前点的颜色是本身就有的
{
if(!marge[x][y])//如果与当前点相邻的点(x,y)也为曾使用过魔法
{
if(color[x][y] != -)//如果点(x,y)有色,但并不是因为魔法而产生的
{
//如果当前点可以放缩dp[x][y]
if(dp[x][y] > dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]))
{
dp[x][y]=dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]);
if(!in[x][y])//被放缩的点(x,y)如果不在队列中,加入队列
in[x][y]=true,myqueue.push(P(x,y));
}
}
else//如果无色,通过使用魔法将其变为与当前点颜色相同的点,并被放缩了dp[][]
{
marge[x][y]=true;
color[x][y]=color[p.first][p.second];
dp[x][y]=dp[p.first][p.second]+;
if(!in[x][y])
in[x][y]=true,myqueue.push(P(x,y));
}
}
else if(dp[x][y] > dp[p.first][p.second]+)//如果点(x,y)在之前使用过魔法,就需要判断,当前为使用过魔法的点是否可以放缩dp[x][y]
{
dp[x][y]=dp[p.first][p.second]+;
color[x][y]=color[p.first][p.second];
if(!in[x][y])
in[x][y]=true,myqueue.push(P(x,y));
}
}
else if(!marge[x][y] && color[x][y] != -)//如果当前点的使用过魔法的,也就意味这当前点的颜色是通过魔法变来的,那么,只有当其临近点(x,y)含有的颜色是其本身就有的才有资格判断是否可以被放缩
{
if(dp[x][y] > dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]))
{
dp[x][y]=dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]);
if(!in[x][y])
myqueue.push(P(x,y)),in[x][y]=true;
}
}
}
}
}
printf("%d\n",dp[m][m] == INF ? -:dp[m][m]);
}
void Init()
{
mem(dp,INF);
mem(in,false);
mem(marge,false);
mem(color,-);
}
int main()
{
scanf("%d%d",&m,&n);
Init();
for(int i=;i <= n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
scanf("%d",&color[x][y]);
}
Solve();
}

  

洛谷 P3956 棋盘(BFS)的更多相关文章

  1. 2017普及组D1T3 洛谷P3956 棋盘

    2017普及组D1T3 洛谷P3956 棋盘 原题 题目描述 有一个m×m的棋盘,棋盘上每一个格子可能是红色.黄色或没有任何颜色的.你现在要从棋盘的最左上角走到棋盘的最右下角. 任何一个时刻,你所站在 ...

  2. 洛谷 P3956 棋盘 解题报告

    P3956 棋盘 题目描述 有一个\(m×m\)的棋盘,棋盘上每一个格子可能是红色.黄色或没有任何颜色的.你现在要从棋盘的最左上角走到棋盘的最右下角. 任何一个时刻,你所站在的位置必须是有颜色的(不能 ...

  3. 洛谷 P3956 棋盘

    题目描述 有一个m ×m的棋盘,棋盘上每一个格子可能是红色.黄色或没有任何颜色的.你现在要从棋盘的最左上角走到棋盘的最右下角. 任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的), 你只能向上 ...

  4. 洛谷 P3956 棋盘(记忆化搜索)

    嗯... 题目链接:https://www.luogu.org/problem/P3956 这是一道比较好搜的题,注意一些剪枝.预处理和魔法的处理问题(回溯). AC代码: #include<c ...

  5. 洛谷 P3956 棋盘 题解

    每日一题 day5 打卡 Analysis 深搜+剪枝+瞎jb判断 1.越界 2.这个点无色 3.当前的价值已经比答案大 三种情况要剪枝 我搜索里判断要不要施法的时候没判断上一次有没有施法,白调了0. ...

  6. 洛谷p3956 棋盘(NOIP2017 t3)

    在noip考场上本来以为只能骗暴力分,没想到最后A了: 本蒟蒻的做法比较简(zhi)单(zhang):记忆化深搜(考场上本来是想打广搜的,但我深搜稳一点就这样打了): 具体:每个点用一个f数组记录当前 ...

  7. 洛谷P1436 棋盘分割

    洛谷题目链接 动态规划: 我们设状态$f[i][j][o][p][k]$表示一个矩形,左上角顶点坐标为$(i,j)$,右下角顶点坐标为$(o,p)$时分割了$k$次,也就是说现在是$k+1$块 我们考 ...

  8. 【洛谷p3956】棋盘

    日常blog(✧◡✧) 棋盘[题目链接] 算法: 然后这是2017普及组: first.关于颜色处理:让c[i][j]=color+1:这样无色=0,红色=1,黄色=2: 然后其实是记忆化,将记答案的 ...

  9. 洛谷 P1141【BFS】+记忆化搜索+染色

    题目链接:https://www.luogu.org/problemnew/show/P1141 题目描述 有一个仅由数字 0 与 1 组成的n×n 格迷宫.若你位于一格0上,那么你可以移动到相邻 4 ...

随机推荐

  1. 基于bootstrap表单登录(带验证码)

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!-- ...

  2. 第三次作业 (一)----------------------Visual Studio 2015的安装及单元测试

    这是第三周的第一个作业,Visual Studio 2015的安装及单元测试. 我的电脑之前安装过Visual Studio 2015,但是在安装过程中我从来没有留意过各种注意事项,所集正好借此作业的 ...

  3. 《吃了么》Alpha版本发布说明

    1.功能描述  功能一  查询周边餐厅 选中一条后,会跳转到相应餐厅的网址,获取具体的信息: 功能二 查询指定地点地餐厅 功能三 查询菜谱 具体的菜谱: 还有收藏夹的功能,点击标题栏的心形图标可以将菜 ...

  4. 2-Twenty Second Scrum Meeting-20151222

    任务安排 成员 今日完成 明日任务 闫昊 服务器关闭,开发停滞……  …… 唐彬 服务器关闭,开发停滞……  …… 史烨轩  服务器关闭,开发停滞……  …… 余帆   路径保存 路径整合 金哉仁   ...

  5. beta版说明书

    项目名称:GoGoing 软件使用说明: 在主界面是可以点击选择景点门票区间来选择景点,同时也可搜索景点显示信息. 还可以通过定位功能显示附近景点. 点开门票区间后是一些景点的图片和简介,还可以通过距 ...

  6. Timer定时执行

    //定时器 public void timeTask(String hh,int n) {//hh="8:30:00",n=12 Timer timer = new Timer() ...

  7. Effective C++(第三版)笔记 ---- 第一部分让自己习惯C++

    内容从侯捷译版的<Effective C++>(第三版)摘录 条款一 C++作为一个多种范式融合的语言,可以看成是语言的联邦,它包含了一下四种主要的次语言: C.C++以C为基础,很多时候 ...

  8. [转帖]从1G到5G

    一文看懂无线通信:从1G到5G 投递人 itwriter 发布于 2019-02-03 15:25 评论(2) 有280人阅读 [收藏] « » 文/老和山下的小学僧 最近太邪乎,先引用一个马克思政治 ...

  9. FICO基础知识(二)

    FI中的maser data: COA (Chart Of Account)  科目表 Account 科目 Vendor master dada  供应商主数据 Customer master da ...

  10. 操作系统+编程语言的分类+执行python程序的两种方式+变量

    1.什么是操作系统? 操作系统就是一个协调\管理\控制计算机硬件资源与软件资源的一个控制程序. 2.为何要操作系统? a.把复杂的硬件操作封装成简单的功能\接口用来给用户或者程序来使用(文件) b.把 ...