NOJ1053 恶魔城 dfs+二分求解

       对半搜索是二分搜索的一种简单应用。实现原理十分简单:以对半方式分割有序表,根据mid的值决定下一次选择左或者右分割区间,重复操作直至mid等于查找元素或者left大于right为止,其原理很容易理解,在此不赘述。

    在复习完二分搜索后,想在oj上找一道题练练手,于是选择了下面的这道noj1053恶魔城这一道题。题目如下:

恶魔城

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 340            测试通过 : 71 

比赛描述

上帝需要创造一位战士去消灭撒旦,这位战士必须要穿过恶魔城才能与撒旦决斗。恶魔城内有M条连接N个路口(从1到N编号)的街道,每一条街道都是单向的(也就是说你不能逆着该街道指定的方向走),并且在城内无论怎么走都不可能走回原来走过的地方。开始的时候,战士的生命力(HP)为INITHP、站在1号路口,而撒旦在第N号路口等待着他。每一条街道上都有许多魔鬼,但是也有一些街道已经被上帝派去的天使占领了。当战士经过连接i号向j号路口的街道时,如果占领该街道的是恶魔,那么他的HP先加倍然后减少L[i,j],我们记为A[i,j]=-L[i,j];如果占领该街道的是天使,那么他的HP就会先加倍然后增加L[i,j],我们记为A[i,j]=+L[i,j];如果该街道不存在,那么A[i,j]=0。如果某一时刻战士的HP<=0,那么他会死亡。因为这个战士将非常无敌,当他见到撒旦的时候只要还活着,就能一口气把撒旦消灭,所以上帝不希望让他的INITHP过高。
你的任务:给定N,A[1..N,1..N],求最小的INITHP,使这个战士能够活着见到撒旦。


输入

文件第一行有一个正整数N(3 ≤ N ≤ 100),下面跟着的第i行第j个数为A[i,j](绝对值不超过10000的整数)。

输出

输出所求最小的INITHP。

样例输入

4
0 -4 0 -10
0 0 +3 0
0 0 0 -14
0 0 0 0

样例输出

4

     问题分析:该问题是一道dfs和二分搜索相结合的题目,以二分法确定hp的最小,再根据dfs判定hp是否符合要求。这一类题目还是做得太少,得多加训练。下面贴上AC了的代码及代码注释:

//该题是一道较为容易理解的dfs 题 它的主要变化是hp的控制  使用二分搜索实现最小hp的求取
//dfs+二分搜索
#include<stdio.h>
#define MAX_P 100
int a[MAX_P][MAX_P];         //二维数组记录地图状态
bool vis[MAX_P];         //vis数组记录是否被访问  因题目要求不可以重复走一条路线
bool dfs(int n, int pos, int hp) //dfs判断能否结束撒旦
{
	if(hp<=0) 					//一开始是0的话也会死
		return 0;
	if(pos==n-1 || hp>10000) 	//a[pos][i]<10000,hp>=10000,那么hp*2+a[pos][i]肯定大于0
		return 1;
	vis[pos]=1;    //从该点出发   标记该点访问为1表示已访问
	for(int i=0; i<n; i++)
	{
		if(a[pos][i]!=0 && !vis[i] && dfs(n,i,hp*2+a[pos][i]))
		return 1;
	}
	vis[pos]=0; //若从该点出发没有到达终点的路  则将该点标记为未访问过 返回上层递归调用
	return 0;
}
int getMinHP(int n)//使用二分法获取最小的hp的值
{
	int low=0, high=10000,mid;//初始化
	while(low<high) //二分法结构
	{
		mid = (low+high)>>1;
		for(int i=0; i<n; i++)  //每次调用需初始化vis数组
			vis[i] = 0;
		if(dfs(n,0,mid)) //如果hp为mid时能够到达终点  则在0-mid之间继续找小的hp值
			high = mid;
		else   //如果不能  则增大mid的值  在mid到 high之间寻找hp可行的值
			low = mid+1;
	}
	return low;
}
int main()
{
	int i,j,n;
	scanf("%d",&n);
	for(i=0; i<n; i++)
		for(j=0; j<n; j++)
			scanf("%d",&a[i][j]);
	printf("%d\n",getMinHP(n));
}
       题目不是很复杂,二分法应用问题还是较多,需要多做此方面的训练。
    特记下,留待来日回顾。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
西北工业大学NOJC程序设计习题答案(非本人制作,侵删) 1.“1“的传奇 2.A+B 3.A+BⅡ 4.AB 5.ACKERMAN 6.Arithmetic Progressions 7.Bee 8.Checksum algorithm 9.Coin Test 10.Dexter need help 11.Double 12.Easy problem 13.Favorite number 14.Graveyard 15.Hailstone 16.Hanoi Ⅱ 17.Houseboat 18.Music Composer 19.Redistribute wealth 20.Road trip 21.Scoring 22.Specialized Numbers 23.Sticks 24.Sum of Consecutive 25.Symmetric Sort 26.The Clock 27.The Ratio of gainers to losers 28.VOL大学乒乓球比赛 29.毕业设计论文打印 30.边沿与内芯的差 31.不会吧,又是A+B 32.不屈的小蜗 33.操场训练 34.插入链表节点 35.插入排序 36.插入字符 37.成绩表计算 38.成绩转换 39.出租车费 40.除法 41.创建与遍历职工链表 42.大数乘法 43.大数除法 44.大数加法 45.单词频次 46.迭代求根 47.多项式的猜想 48.二分查找 49.二分求根 50.发工资的日子 51.方差 52.分离单词 53.分数拆分 54.分数化小数 55.分数加减法 56.复数 57.高低交换 58.公园喷水器 59.韩信点兵 60.行程编码压缩算法 61.合并字符串 62.猴子分桃 63.火车站 64.获取指定二进制位 65.积分计算 66.级数和 67.计算A+B 68.计算PI 69.计算π 70.计算成绩 71.计算完全数 72.检测位图长宽 73.检查图像文件格式 74.奖金发放 75.阶乘合计 76.解不等式 77.精确幂乘 78.恐怖水母 79.快速排序 80.粒子裂变 81.链表动态增长或缩短 82.链表节点删除 83.两个整数之间所有的素数 84.路痴 85.冒泡排序 86.你会存钱吗 87.逆序整数 88.排列 89.排列分析 90.平均值函数 91.奇特的分数数列 92.求建筑高度 93.区间内素数 94.三点顺序 95.山迪的麻烦 96.删除字符 97.是该年的第几天 98.是该年的第几天? 99.数据加密 100.搜索字符 101.所有素数 102.探索合数世纪 103.特殊要求的字符串 104.特殊整数 105.完全数 106.王的对抗 107.危险的组合 108.文件比较 109.文章统计 110.五猴分桃 111.小型数据库 112.幸运儿 113.幸运数字”7“ 114.选择排序 115.寻找规律 116.循环移位 117.延伸的卡片 118.羊羊聚会 119.一维数组”赋值“ 120.一维数组”加法“ 121.勇闯天涯 122.右上角 123.右下角 124.圆及圆球等的相关计算 125.圆及圆球等相关计算 126.程序员添加行号 127.找出数字 128.找幸运数 129.找最大数 130.整数位数 131.重组字符串 132.子序列的和 133.子字符串替换 134.自然数立方的乐趣 135.字符串比较 136.字符串复制 137.字符串加密编码 138.字符串逆序 139.字符串排序 140.字符串替换 141.字符串左中右 142.组合数 143.最次方数 144.最大乘积 145.最大整数 146.最小整数 147.最长回文子串 148.左上角 149.左下角

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值