试题 算法训练 步与血
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
有n*n的方格,其中有m个障碍,第i个障碍会消耗你p[i]点血。初始你有C点血,你需要从(1,1)到(n,n),并保证血量大于0,求最小步数。
输入格式
第一行3个整数n,m,c,表示棋盘大小、障碍数量和你的血量
接下来m行,每行描述一个障碍。包含三个整数x y p,分别表示障碍在第x行第y列,消耗血量为p。
输出格式
如果可以到输出步数,如果不可以,输出"No"。
样例输入
10 10 10
2 8 35
1 10 25
9 9 63
5 6 46
2 6 43
8 7 92
5 3 54
3 3 22
7 9 96
9 10 13
样例输出
18
数据规模和约定
输入数据中每一个数的范围。
0<n,m<100,
前言:做DFS还是稍显生疏,用了好长时间才调试对,对递归使用仍不够熟练QAQ
思路与解析:
1、这是一道典型的DFS,因为本道题只要求你得出你走到终点所需要的步数,所以不用过于考虑过程走的是不是最优解(万一让你算出来走到终点所剩的最高血量呢?),所以这道题比较简单,无论路径是怎样,从1,1走到n,n一共肯定需要走(n - 1)* 2步,只需要判断能不能活着到终点即可:
if(活着到终点)
printf("%d", n * 2 - 2);
else
printf("No");
2、那么先建立一个n*n的数组储存地图,然后dfs一下:
int n, m, heart; //初始化一下
cin >> n >> m >> heart;
memset(a, 0, sizeof a);
int i, j, k;
while (m--)
{
cin >> i >> j >> k;
a[i][j] = k;
}
// x,y是坐标,n是边界,blood是剩余血量
void dfs(int x, int y, int n, int blood)
{
if (x == n && y == n)
{
flag = 1; //flag等于1代表活着到终点
}
if(flag == 1) return; //活着就一直return回main
if ( x < n && y <= n && blood - a[x + 1][y] > 0)
{
//如果可以向右走就 ,x + 1, y
dfs(x + 1, y, n, blood - a[x + 1][y]);
}
if ( x <= n && y < n && blood - a[x][y + 1] > 0)
{
//如果可以向下走就 ,x, y + 1
dfs(x, y + 1, n, blood - a[x][y+1]);
}
}
3、初始血量应该是:
int blood = heart - a[1][1]; //起始血量要减去a[1][1]
AC代码如下:
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int a[102][102]; //地图
int flag=0; //ans
void dfs(int x, int y, int n, int blood)
{
if (x == n && y == n)
{
flag = 1;
}
if(flag == 1) return;
if ( x < n && y <= n && blood - a[x + 1][y] > 0)
{
dfs(x + 1, y, n, blood - a[x + 1][y]);
}
if ( x <= n && y < n && blood - a[x][y + 1] > 0)
{
dfs(x, y + 1, n, blood - a[x][y+1]);
}
}
int main() {
int n, m, heart;
cin >> n >> m >> heart;
int blood;
memset(a, 0, sizeof a);
int i, j, k;
while (m--)
{
cin >> i >> j >> k;
a[i][j] = k;
}
blood = heart - a[1][1];
dfs(1,1,n,blood);
if(flag)
printf("%d", n * 2 - 2);
else
printf("No");
return 0;
}