C语言实现 蓝桥杯 算法训练 步与血

试题 算法训练 步与血

                                                                                  蓝桥杯试题解答汇总链接

资源限制

       时间限制: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,

试题解析

步数最小就得每次只能向下或向右走,那么这样就很容易取动态规划了设dp.co[i][j]为走到(i,j)位置需要的步数那么dp.co[i][j]=min(dp.co[i-1][j],dp.co[i][j-1])但其中有障碍所以还需要保存到每个位置的血量>0,否则说明这个点不能走


代码
#include <stdio.h>
typedef struct s{
	int co[101][101];// 走到(i,j)需要的最小步数 
	int blood[101][101];// 走到(i,j)剩余的血量 
}step;
int main() {// n、m、c、x、y、p对应题意 
	int n, m, c, x, y, p, i, j;
	scanf("%d%d%d",&n,&m,&c);
	int chess[101][101] = {0};// 棋盘chess的值为此处消耗的血量 
	for(i = 0;i < m; ++i) {
		scanf("%d%d%d",&x,&y,&p);
		chess[x][y] = p;
	}
	step dp;
	dp.blood[1][1] = c;// 初始化血量 
	dp.co[1][1] = 0;// 初始化步数 
	for(i = 2;i <= n; ++i) {// 初始化第一行第一列 
		dp.co[1][i] = dp.co[1][i-1]+1;// 从(1,i-1)到(1,i)步数+1 
		dp.blood[1][i] = dp.blood[1][i-1]-chess[1][i];// 去掉消耗的血量 
		if(dp.blood[1][i] <= 0) {// 血量不大于0说明这里不能走步数设为0 
			dp.co[1][i] = 0;
		}
		dp.co[i][1] = dp.co[i-1][1]+1;
		dp.blood[i][1] = dp.blood[i-1][1]-chess[i][1];
		if(dp.blood[i][1] <= 0) {
			dp.co[i][1] = 0;
		}
	}
	for(i = 2;i <= n; ++i) {// 从(2,2)开始递推 
		for(j = 2;j <= n; ++j) {
			if(dp.co[i-1][j]>0 && dp.co[i][j-1]>0) {// 左边和上边步数不为0说明都能通行 
				if(dp.co[i-1][j] <= dp.co[i][j-1]) {
					dp.co[i][j] = dp.co[i-1][j]+1;
					dp.blood[i][j] = dp.blood[i-1][j]-chess[i][j];
					if(dp.blood[i][j] <= 0) {
						dp.co[i][j] = 0;
					}
				}else {
					dp.co[i][j] = dp.co[i][j-1]+1;
					dp.blood[i][j] = dp.blood[i][j-1]-chess[i][j];
					if(dp.blood[i][j] <= 0) {
						dp.co[i][j] = 0;
					}
				}
			}else if(dp.co[i-1][j] == 0) {// 有一个为0取另外一个 
				dp.co[i][j] = dp.co[i][j-1]+1;
				dp.blood[i][j] = dp.blood[i][j-1]-chess[i][j];
				if(dp.blood[i][j] <= 0) {
						dp.co[i][j] = 0;
				}
			}else{
				dp.co[i][j] = dp.co[i-1][j]+1;
				dp.blood[i][j] = dp.blood[i-1][j]-chess[i][j];
				if(dp.blood[i][j] <= 0) {
						dp.co[i][j] = 0;
				}
			}
		}
	}
	if(dp.blood[n][n] > 0) {
		printf("%d",dp.co[n][n]);
	}else {
		printf("No");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Derrick-Xu

谢大哥打赏,我会继续努力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值