【dp】小白月赛-迷雾森林

引言:
好久没有做题了,今天做了发现自己打题这方面确实差别人太多了,慢慢的从基础开始吧。本来我以为这是一道dfs,虽然看复杂度不像,但是我没有想到其他的解法,百度了才发现这是一道dp,那就记录一下吧。
题目:迷雾森林

链接:https://ac.nowcoder.com/acm/contest/2272/B
来源:牛客网

题目描述
赛时提示:保证出发点和终点都是空地

帕秋莉掌握了一种木属性魔法
这种魔法可以生成一片森林(类似于迷阵),但一次实验时,帕秋莉不小心将自己困入了森林
帕秋莉处于地图的左下角,出口在地图右上角,她只能够向上或者向右行走

现在给你森林的地图,保证可以到达出口,请问有多少种不同的方案

答案对2333取模

输入描述:
第一行两个整数m , n表示森林是m行n列
接下来m行,每行n个数,描述了地图
0 - 空地
1 - 树(无法通过)
输出描述:
一个整数表示答案
示例1
输入
复制
3 3
0 1 0
0 0 0
0 0 0
输出
复制
3
备注:
对于30%的数据,n,m≤100
对于100%的数据,n,m≤3,000
数据规模较大,请使用较快的输入方式,以下为快速读入模板

templateinline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<‘0’||c>‘9’)if(c==’-’)flag=-1;res=c-‘0’;
while((c=getchar())>=‘0’&&c<=‘9’)res=res10+c-‘0’;res=flag;
}

scanf("%d",&x) -> read(x)
cin>>x -> read(x)

(调用方式:read(要读入的数))
1.贴出错误代码(超时):

#include<bits/stdc++.h>
using namespace std;
template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

const int maxn=3005;
int a[maxn][maxn],book[maxn][maxn];
int n,m,sum=0;
int dir[2][2]={-1,0,
				0,1};

void dfs(int x,int y){
	if(x==1&&y==n){
		sum++;
		sum%=2333;
	}
	for(int i=0;i<2;i++){
		int tx=x+dir[i][0];
		int ty=y+dir[i][1];
		if(tx<1||ty>n||a[tx][ty]==1||book[tx][ty]==1) continue;
		book[tx][ty]=1;
		dfs(tx,ty);
		
	}
	book[x][y]=0;
	return;
}
int main(){
	read(m);
	read(n);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			read(a[i][j]);	
		}
	}
	book[m][1]=1;
	dfs(m,1);
	printf("%d\n",sum);
	return 0;
}

2.正确解法dp:到每个点的方案数等于到它下方的点方案数与到它左边点的方案数之和。
方程:dp[i][j]=dp[i+1][j]+dp[i][j-1]

扫描二维码关注公众号,回复: 9211158 查看本文章
#include<bits/stdc++.h>
using namespace std;
template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

const int maxn=3005;
int a[maxn][maxn],f[maxn][maxn];
int n,m,sum=0;

int main(){
	read(m);
	read(n);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			read(a[i][j]);	
		}
	}
	//起点到起点只有一条路
	f[m][1]=1; 
	//从下到上
	for(int i=m;i>=1;i--){
		//从左到右
		for(int j=1;j<=n;j++){
			//加上到当前点下方点的方案数
			if(a[i+1][j]==0&&(i+1)<=m) f[i][j]=(f[i][j]+f[i+1][j])%2333;
			//加上到当前点左边点的方案数
			if(a[i][j-1]==0&&(j-1)>=1) f[i][j]=(f[i][j]+f[i][j-1])%2333;
		}
	}
	//最终答案就是到终点的方案数
	printf("%d\n",f[1][n]);
	return 0;
}
发布了54 篇原创文章 · 获赞 78 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/tran_sient/article/details/104340487