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点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦 ...
随机推荐
- Hive鲜为人知的宝石-Hooks
本来想祝大家节日快乐,哎,无奈浪尖还在写文章.谴责一下,那些今天不学习的人.对于今天入星球的人,今天调低了一点价格.减少了20大洋.机不可失失不再来.点击阅读原文或者扫底部二维码. hive概述 Hi ...
- DES与MD5加密
using System; using System.Data; using System.Configuration; using System.Web; using System.Security ...
- redis(六)---- 简单延迟队列
延迟队列的应用场景也很常见,例如:session的超时过期.自动取消未付款订单等等.redis中有一种数据结构叫做zset,即有序集合.元素类型为String类型,且元素具有唯一性不能重复,每个元素可 ...
- OSS 图片处理流程
1.步骤一 2.步骤二 3.步骤三 4.步骤四 5.步骤五(步骤4完成会自动添加cname用户解析,不需要自己去加,只需要点击进来看下是否添加成功即可) 通过以上步骤就可以实现了图片服务的配置
- php封装一个接口类
<?phpClass Response{//返回数据 public static function show($code,$message='',$data='',$type = 'json', ...
- DFS判断连通图
因为是连通图,所以从任意一点出发,一定可以通过一遍深度优先遍历就能走过所有的点和边,就可以利用这个性质来很容易的通过DFS判断图是否为连通图 下面是具体算法:
- Windows下C extension not loaded for Word2Vec, training will be slow.解决方法
在网上看了好多个博客,都没有很好解决,最后google.. 大概问题就是gensim库在安装时没有和其他一些包关联起来(可能是由于用pip安装的gensim导致这个问题),所以在用Word2Vec时没 ...
- js样式添加
document.getElementsByName("spans")[index].style.color = "blue";
- 85.常用的返回QuerySet对象的方法使用详解:defer,only
defer(),only(): 这两个方法都会返回一个"QuerySet"对象,并且这个"QuerySet"中装的是模型,不像values()和values_l ...
- jquery 第二节 Dom和jQuery的互相转换
1.Dom转jQuery Dom对象: var v_dom = document.getElementById("name"); 转换: jQuery对象: var v_jq ...