问题 D: LZY逃命路线总数
链接:http://acm.oinsm.com/problem.php?cid=1041&pid=3
时间限制: 1 Sec 内存限制: 32 MB
题目描述
2019年夏天,LZY开开心心的骑着电动车出去玩,结果一不留神,他骑着电动车进入了一只恶犬的领地。恶犬发现它的领地被LZY侵犯了,立马去追LZY,准备咬他一大口。
LZY慌忙逃窜,但是他的电动车电量即将耗尽,现在请你帮忙计算一下,LZY能成功逃脱恶犬领地的路线一共有多少条?
周赛成功AC该题的同学结束后找营长领取红包~~
输入
测试样例由多组测试数据组成。每组测试数据第一行输入5个整数 n , m ( 1 <= n,m <= 50) , t ( 1 <= t <= 50 ), i ( 0 <= i < n ) , j ( 0 <= j < m )
我们把恶犬的领地看做一个二维矩阵,其中 n 和 m代表恶犬的领地范围的行和列
t 代表LZY的电动车最多还能移动多少格 (只能上下左右移动,移动一次 t - 1 ,当 t 为 0 时则LZY不能移动)
i 和 j代表LZY被恶犬发现时的坐标
输出
输出LZY能够逃离恶犬的领地范围的路线总数,只要逃出恶犬领地范围(超出边界)则视为成功逃脱,由于答案很大,所以你需要将你的答案对 1000000007 取模。
样例输入 Copy
2 2 2 0 0
样例输出 Copy
6
提示
1.下图是对样例的解释
2.LZY一旦跑出边界,他是不会再回来了(他也不傻)
3.只要LZY还没跑出边界,他可以重复经过他之前经过的所有网格
思路:
- 建立三维数组,x,y,能量。
- 能量不够时返回0
- 什么条件算走出去
- 记忆化每一个走过的点
- 难题就是怎么剪枝。什么条件下是绝对走不出去的。两点之间直线最短,如果当点加上能量到达不了边缘时,说明不管怎么走都出不去就把它剪枝了。
- 切记直接对 1000000007 取模,自定义变量MOD会超时,说多了都是泪。
正确代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int n,m,t;
long long dp[55][55][55];
//long long MOD=1000000007; 如果用MOD取模会超时
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
long long dfs(int x,int y,int time){
//cout<<x<<" "<<y<<" "<<dp[x][y][time]<<endl;
if(x-time>=0&&y-time>=0&&x+time<n&&y+time<m){//走不出去时
return 0;
}
if(x<0||y<0||x>=n||y>=m){//走出去
return 1;
}
if(time<=0) return 0;//能量不够
if(dp[x][y][time]>0) return dp[x][y][time]%1000000007;//这个点走过时
//dp[x][y][time] =0;如果初始值为-1时,我们要将它改为0;
for(int i=0;i<4;i++){//跑方向
int dx=x+dir[i][0];
int dy=y+dir[i][1];
//dp[x][y][time]+=dfs(dx,dy,time-1);
dp[x][y][time]=(dp[x][y][time]+dfs(dx,dy,time-1)%1000000007)%1000000007;
}
return dp[x][y][time]%1000000007;
}
int main(){
ios::sync_with_stdio(false);
//cin.tie(0);cout.tie(0);
int x,y;
while(cin>>n>>m>>t>>x>>y){
memset(dp,0,sizeof(dp));//初始化 -1,0都可以
cout<<dfs(x,y,t)<<endl;
}
return 0;
}