【题目描述】 原题目链接地址:
  有一个m × m的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。
任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的),你只能向上、下、左、右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 1 个金币。
  另外,你可以花费 2 个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用,而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法;只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。
  现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?
【输入格式】
  数据的第一行包含两个正整数 m,n,以一个空格分开,分别代表棋盘的大小,棋盘上 有颜色的格子的数量。
  接下来的 n 行,每行三个正整数 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
 
图片省略~~
-------------------------------------------------------------------------------

分析:记忆化搜索, 用DP[i][j]表示走到(i,j)时的最小代价,如果当前深搜到的代价sum>=dp[i][j],直接return ; 否则更新dp[i][j]——表示这是一个更优的解,然后继续递归!与sum的判断,每一个if条件都不能省!

/*  同种颜色可以直接跳上去;/0红色,1黄色,-1空格
    跳到不同颜色花费1金币;
   op=1, 或者跳到空格-1上,开销为2,然后 再跳到有色的地方--开销1或者0;*/
-----------------------------------------------------------------------------------
 

AC题解:

  

int m,n;   //和题意描述的相反,m表示有颜色的点数,n表示正方形的边长
int G[N][N];//存贮每个格点的颜色情况!
int ans;
int dir[][]={ {-,},{,},{,-},{,} }; int dp[N][N];//用DP[i][j]表示走到(i,j)时的最小代价 void dfs(int x,int y,int sum,int op,int col){
// printf("**(%d,%d) sum=%d op=%d col=%d\n",x,y,sum,op,col);
if(x==n&&y==n){
ans=min(ans,sum);
// printf("________sum=%d\n",sum);
return ;
}
for(int i=;i<;i++){
int dx=x+dir[i][];
int dy=y+dir[i][];
if(dx<||dy<||dx>n||dy>n)
continue;
if(sum>=dp[dx][dy])//进行优化,dp[][]记忆之前达到该点的最小花费!
continue ;
if(G[dx][dy]>=){
if(col==G[dx][dy]){//代价为零,同种颜色!
dp[dx][dy]=sum;
dfs(dx,dy,sum,,col);
}
else{ //代价为1,异种颜色,可以非一次!
dp[dx][dy]=sum+;
dfs(dx,dy,sum+,,!col);
}
}
else{
if(op==&&dp[dx][dy]>sum+ ){ //上面有条件:dp[dx][dy]>sum
dp[dx][dy]=sum+;
dfs(dx,dy,sum+,,col);//op改为1表示跳到空格上了,下一步要小心!
} } }
} int main(){ // freopen("checkerboard.in","r",stdin);
// freopen("checkerboard.out","w",stdout);
int x,y,z;
scanf("%d%d",&n,&m);
memset(G,-,sizeof(G));
for(int i=;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
G[x][y]=z;//0红色,1黄色
}
memset(vis,,sizeof(vis)); ans=inf;
memset(dp,inf,sizeof(dp));
dp[][]=;
dfs(,,,,G[][]);//省时需要记忆化搜索!! if(ans==inf){
printf("-1\n");
}
else{
printf("%d\n",ans);
}
return ;
}

(点开有注释呦~~)

【记忆化搜索】[NOIP-2017--普及组] -- 棋盘的更多相关文章

  1. 【NOIP 2017 普及组】 跳房子

    裸的单调队列优化dp+二分 我居然还调了挺久 日常审题错误 #include <bits/stdc++.h> using namespace std; typedef long long ...

  2. NOIP 2017 逛公园 记忆化搜索 最短路 好题

    题目描述: 策策同学特别喜欢逛公园.公园可以看成一张N个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. ...

  3. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

  4. 【noip 2009】 乌龟棋 记忆化搜索&动规

    题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...

  5. 2017广东工业大学程序设计竞赛决赛 题解&源码(A,数学解方程,B,贪心博弈,C,递归,D,水,E,贪心,面试题,F,贪心,枚举,LCA,G,dp,记忆化搜索,H,思维题)

    心得: 这比赛真的是不要不要的,pending了一下午,也不知道对错,直接做过去就是了,也没有管太多! Problem A: 两只老虎 Description 来,我们先来放松下,听听儿歌,一起“唱” ...

  6. poj1191 棋盘分割【区间DP】【记忆化搜索】

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16263   Accepted: 5812 Description ...

  7. POJ 1191 棋盘分割 【DFS记忆化搜索经典】

    题目传送门:http://poj.org/problem?id=1191 棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submission ...

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

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

  9. 最大联通子数组之和(dfs,记忆化搜索,状态压缩)

    最大联通子数组,这次的题目,我采用的方法为dfs搜索,按照已经取到的数v[][],来进行搜索过程的状态转移,每次对v[][]中标记为1的所有元素依次取其相邻的未被标记为1的元素,将其标记为1,然而,这 ...

随机推荐

  1. 如何优雅的处理 async/await 异常

    参考链接:https://cloud.tencent.com/developer/article/1470715 参考链接:https://www.jianshu.com/p/2935c0330dd2

  2. 怎样ubuntu下命令行终端显示短路径

    参考:http://blog.sina.com.cn/s/blog_b71132f001016cmm.html ubuntu的终端命令行默认是长路径,即把路径深度全部显示出来,操作起来不是很方便,下面 ...

  3. kafka原理分析

    #kafka为什么有高吞吐量 1 由于接收数据时可以设置request.required.acks参数,一般设定为1或者0,即生产者发送消息0代表不关心kafka是否接收成功,也就是关闭ack:1代表 ...

  4. C++ 计算定积分、不定积分、蒙特卡洛积分法

    封装成了一个类,头文件和源文件如下: integral.h #pragma once //Microsoft Visual Studio 2015 Enterprise #include <io ...

  5. Python进阶:生成器--懒人版本的迭代器

    从容器.可迭代对象谈起 所有的容器都是可迭代的(iterable),迭代器提供了一个next方法.iter()返回一个迭代器,通过next()函数可以实现遍历. def is_iterable(par ...

  6. 利用strace & Perf分析MySQL

    strace介绍及用途 strace是一个用于诊断,分析linux用户态进程的工具 类似的工具pstrace,lsof,gdb,pstrack strace观察mysqld对my.cnf 配置文件的加 ...

  7. xorm表结构操作实例

    获取数据库信息 package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "git ...

  8. 【转载】使用Class.getResource和ClassLoader.getResource方法获取文件路径

    自从转投Java阵营后,一直发下Java程序的路径读取异常麻烦,因此查阅了比较多的版本内容,整合了一份自己的学习笔记.主要使用Class及通过ClassLoader来动态获取文件路径. 查阅链接如下: ...

  9. 使用代码浏览WPF控件模版

    纯代码创建,不需要创建界面,创建WPF工程后,直接复制代码就可以使用. 当你手头没有Blend,又不记得以下这段代码,但是又想浏览控件模版的时候,就可以直接复制拿来用了. public partial ...

  10. Spring Boot整合Spring Security自定义登录实战

    本文主要介绍在Spring Boot中整合Spring Security,对于Spring Boot配置及使用不做过多介绍,还不了解的同学可以先学习下Spring Boot. 本demo所用Sprin ...