NOIP2002 过河卒(DFS,DP)
https://www.luogu.org/problem/P1002
题目描述
输入描述:
输入B点的坐标(n,m)以及对方马的坐标(X,Y){不用判错}
输出描述:
输出一个整数(路径的条数)。
示例1
输入
输出
说明/提示
结果可能很大!
一开始按DFS做,超时
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const double PI=acos(-);
const int maxn=;
using namespace std;
//ios::sync_with_stdio(false);
// cin.tie(NULL); int n,m,x,y;
int ans; bool judge(int a,int b)
{
if(a==x&&b==y)
return false;
if(a==x-&&b==y-)
return false;
if(a==x-&&b==y-)
return false;
if(a==x+&&b==y-)
return false;
if(a==x+&&b==y-)
return false;
if(a==x-&&b==y+)
return false;
if(a==x+&&b==y+)
return false;
if(a==x-&&b==y+)
return false;
if(a==x+&&b==y+)
return false;
return true;
} void DFS(int a,int b)
{
if(a==n&&b==m)
{
ans++;
return ;
}
if(a+<=n&&judge(a+,b))
DFS(a+,b);
if(b+<=m&&judge(a,b+))
DFS(a,b+);
} int main()
{
scanf("%d %d %d %d",&n,&m,&x,&y);
DFS(,);
printf("%d\n",ans);
return ;
}
后来以为if判断太多,换了种方法,依然超时
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const double PI=acos(-);
const int maxn=;
using namespace std;
//ios::sync_with_stdio(false);
// cin.tie(NULL); int n,m,x,y;
int G[][];
int ans; void DFS(int a,int b)
{
if(a==n&&b==m)
{
ans++;
return ;
}
if(a+<=n&&G[a+][b]==)
DFS(a+,b);
if(b+<=m&&G[a][b+]==)
DFS(a,b+);
return ;
} int main()
{
//freopen("testdate.in","r",stdin);
scanf("%d %d %d %d",&n,&m,&x,&y);
G[x][y]=;
if(x->=)
{
G[x-][y-]=;
G[x-][y+]=;
}
if(y->=)
{
G[x-][y-]=;
G[x+][y-]=;
}
if(x->=)
{
G[x-][y+]=;
}
if(y->=)
{
G[x+][y-]=;
}
G[x+][y+]=;
G[x+][y+]=;
DFS(,);
printf("%d\n",ans);
return ;
}
最后意识到,这题没那么简单.
看过题解才明白这题是记忆化递推,或者说是DP
DP题就是要找到状态转移方程,这题的状态转移方程只用手动模拟一下就可以了,就可以得出到每一个点的方案数就是上面和左边的方案数的总和(因为只可以向右走或向下走),具体的状态转移方程是

即可以写成DP[i][j]=max(DP[i][j],DP[i-1][j]+DP[i][j-1])
注意,最大的结果已经超过了int的范围,这是一个坑
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const double PI=acos(-);
const int maxn=;
using namespace std;
//ios::sync_with_stdio(false);
// cin.tie(NULL); int n,m,x,y;
LL DP[][];//DP[i][j]代表从A点到(i,j)的线路条数
bool G[][];//判断这个点有没有马盯着
//马可以走到的位置
int fx[]={,-,-,,,,,-,-};
int fy[]={,,,,,-,-,-,-}; int main()
{
scanf("%d %d %d %d",&n,&m,&x,&y);
n+=;m+=,x+=,y+=;//坐标加2,防止标记马时越界
for(int i=;i<=;i++)//标记马的位置
{
G[x+fx[i]][y+fy[i]]=true;
}
DP[][]=;//初始化
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(G[i][j])
continue;
DP[i][j]=max(DP[i][j],DP[i-][j]+DP[i][j-]);//状态转移方程
}
}
printf("%lld\n",DP[n][m]);
return ;
}
下面粘一个有意思的代码(递推):
我们可以发现一个规律:每个数都等于它上面左边的数的和
#include <iostream>
using namespace std; int n,m,my,mx;
long long a[][]; int main()
{
cin >>n >>m >>my >>mx;//输入数据
n=n+;m=m+;my=my+;mx=mx+; //隔出两格,当要把马可跳到的地方掷成0时不会出错
for(int z=;z<=m;z++)
{
for(int y=;y<=n;y++)
{
a[z][y]=a[z-][y]+a[z][y-]; //将这个数左边和上面的数相加
a[][]=;//由于会把起点掷成0,所以要回归1
a[mx][my]=;//将马的地方掷成0
a[mx+][my+]=;a[mx+][my-]=;//将马可跳到的地方掷成0
a[mx-][my+]=;a[mx-][my-]=;//将马可跳到的地方掷成0
a[mx+][my+]=;a[mx+][my-]=;//将马可跳到的地方掷成0
a[mx-][my+]=;a[mx-][my-]=;//将马可跳到的地方掷成0
}
}
cout <<a[m][n];//输出结果
return ;
}
NOIP2002 过河卒(DFS,DP)的更多相关文章
- SDUT 1265-马停下过河卒(DFS)
马拦过河卒 nid=24#time" title="C.C++.go.haskell.lua.pascal Time Limit3000ms Memory Limit 65536K ...
- 洛谷P1002 过河卒【dp】
棋盘上AA点有一个过河卒,需要走到目标BB点.卒行走的规则:可以向下.或者向右.同时在棋盘上CC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为"马拦过河卒 ...
- NOIP 2002过河卒 Label:dp
题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如 ...
- P1002 过河卒【dp】
P1002 过河卒 题目描述 棋盘上AAA点有一个过河卒,需要走到目标BBB点.卒行走的规则:可以向下.或者向右.同时在棋盘上CCC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制 ...
- 洛谷 - P1002 - 过河卒 - 简单dp
https://www.luogu.org/problemnew/show/P1002 方程很好想,题目也很暴力.感谢题目提示数据会很大. #include<bits/stdc++.h> ...
- 过河卒(Noip2002)(dp)
过河卒(Noip2002) 时间限制: 1 Sec 内存限制: 128 MB提交: 7 解决: 6[提交][状态][讨论版][命题人:quanxing] 题目描述 棋盘上A点有一个过河卒,需要走到 ...
- dp练习(4)——过河卒
1010 过河卒 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 如图,A ...
- 【openjudge】【递推】例3.6 过河卒(Noip2002)
[题目描述] 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1 ...
- 过河卒 NOIp 2002 dp
题目描述 棋盘上AAA点有一个过河卒,需要走到目标BBB点.卒行走的规则:可以向下.或者向右.同时在棋盘上CCC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦 ...
随机推荐
- linux文件编辑VI命令详解
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...
- VMWare WorkStation15--Win10下开机启动虚拟机
参考 https://www.cnblogs.com/qmfsun/p/6284236.html http://www.cnblogs.com/eliteboy/p/7838091.html VMWa ...
- JS实现时间选择器
源代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...
- adaboost 基于错误提升分类器
引自(机器学习实战) 简单概念 Adaboost是一种弱学习算法到强学习算法,这里的弱和强学习算法,指的当然都是分类器,首先我们需要简单介绍几个概念. 1:弱学习器:在二分情况下弱分类器的错误率会低于 ...
- Linux&Win双系统下时间显示不正常的问题
于近期开始研究Linux,目前用的是ubuntu.本想着用Linux搞事情,没想到却被Linux搞了. 我安装的是双系统,Linux&windows的组合.相信刚开始用双系统的小伙伴们一定会碰 ...
- 图解:平衡二叉树,AVL树
学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建 ...
- Java 继承(extends)、抽象类(abstract)的特点用法原理(7)
Java 中的继承 继承: java中的抽象类用法原理: /* 当多个类中出现相同功能,但是功能主体不同, 这是可以进行向上抽取.这时,只抽取功能定义,而不抽取功能主体. 抽象:看不懂. 抽象类的特 ...
- gbdt在回归方面的基本原理以及实例并且可以做分类
对书法的热爱,和编译器打数学公式很艰难,就这样的正例自己学过的东西,明天更新gbdt在分类方面的应用. 结论,如果要用一个常量来预测y,用log(sum(y)/sum(1-y))是一个最佳的选择. 本 ...
- PAT Vocabulary
数字 单词 词性 中文意 常用 音标 non-negative 非负数 non-negative number Positive 正整数 Positive integer Negative 负数 Ne ...
- protobuf编译工具使用
1.下载,配置环境变量 下载地址:https://github.com/google/protobuf/releases,选择protoc-xxx-win64.zip下载 把.exe文件的位置加入到P ...