POJ 3827 Facer is learning to swim
来源:互联网 发布:网络音视频许可证 编辑:程序博客网 时间:2024/05/21 00:48
题目大意:
现有一个游泳的游戏,游泳池是一个N×M的网格(1 ≤ N ≤ 100,1 ≤ M ≤ 1,000),左上角坐标为(1, 1),右下角坐标为(N, M),其中第一行为水面(可以在水面换气),下面的行都是水下,其中第M列的水下都是毒药,游进去会死。现在要从(1, 1)游到(1, M),现有恒定的横下速度1,即每次都会向右前进一格(也可以说是每秒前进一格),纵向速度为v(可变),如果v大于0表示下降潜水,v小于0表示上浮,v等于0表示纵向不动,纵向在下一秒移动的格数为|v|,但是如果x + v <1,其中x为行坐标y为列坐标(为游泳者的当前位置),则下一秒他会达到(1, y + 1),因为他不会飞上天,同样如果x + v > N,则他下一秒的坐标为(N, y + 1),因为他不会钻地。
游泳者每隔k秒就需要到水面换一次气,即在水下时间不得超过k - 1秒(1 ≤ k ≤ 10)。
在每个格子中必会出现两样东西中的一样(不会两个同时出现),一个就是加速器另一个就是钱,加速器可以改变纵向速度(即给纵向速度一个加速度A,-20 ≤ A ≤ 20),而遇到钱就可以捡,钱的值为p(-1,000,000 ≤ p ≤ 1,000,000),但是游泳者还随身携带了一种东西,就是小型变速器,他可以使用无限次,并且在每个格子中最多使用一次(或者不使用),小型变速器只能改变纵向速度,只能边-1或+1,如果加速值为Q的话,则Q = 0, ±1。
现对加速器规则做详细说明(纵向合速度为v + a + q):
1. 如果到达水面,则加速器失效并且垂直速度变为0,如果想在下一秒潜入水下则必须使用随身携带的小型加速器;
2. 当到达底层后遇到加速器,在下一秒其纵向合速度为_v = v + a + q,并且_v + x > N,由于不能钻地,则其下一秒移动到(N, y + 1) 并且_v不变,即在下一个格子总纵向速度仍然为_v,如果在下一个格子中遇到a,则在下一个格子中速度变为_v + a + q。
现在需要合理地使用小型加速器使得游泳者到达(1, M)后能获得最大钱数。
现有多个测例,测例以"0 0 0"结束,每个测例先给出N, M, K,接着给出一个N×M的矩阵,矩阵中元素的形式为"vA"或者"$P“,每个元素以空格隔开,v表示加速器,A为其值,$表示钱,P为钱数,对于每个测例输出到达(1, M)可以获得的最大钱数。
题目链接
注释代码:
/* * Problem ID : POJ 3827 Facer is learning to swim * Author : Lirx.t.Una * Language : C * Run Time : 1969 ms * Run Memory : 924 KB */ #include <stdio.h>#define INF 2000001//分别为泳池长宽的最大值//都从下标1开始计#define MAXN 101#define MAXM 1001#define FMTLEN 20//表示泳池中的格子//money是每个格子中的钱数(可以为负)//acc是accelerator,即加速器表示格子中加速装置对当前速度的改变值(可以为负)//acc范围为[-20, 20]在char的范围内(由于结构体的对齐使用int也无妨)typedef struct { int money; char acc; } Pool;Pool p[MAXN][MAXM];//pool,表示泳池矩阵int dp[MAXM];//dp[i]表示当Facer第i秒到达水面(最上层)时获得的最大钱数int n, m, k;//表示泳池的长、宽以及Facer最多在水面下能连续待k - 1秒char fmt[FMTLEN];//格式字符串voiddfs( int dpth, int x, int y, int tot, int v ) {//有界深度优先搜索//dpth即深度不能超过Facer的水下时间限制k,dpth = 0表示搜索的开始(即一个新的周期) //此时Facer在水面//x表示横向坐标y为纵向坐标(表示水深)//tot表示Facer当前的所有钱数//v表示当前的垂直速度//x > m表示当前Facer已经游出泳池的边界了(超出第m列了)//dpth == k && y > 1,表示当前(即第k秒)Facer仍然在水下,即被淹死了 if ( x > m || dpth == k && y > 1 ) return ;//不能钻地以及浮在空中 if ( y < 1 ) y = 1; else if ( y > n ) y = n; tot += p[y][x].money; if ( dpth && 1 == y ) {//如果Facer离开了起始位置并且又回到了水面//则可以跟新dp值并返回//即每个dp值最多只能影响其后面k个dp值 if ( tot > dp[x] ) dp[x] = tot; return ; } if ( !dpth ) {//如果当前是搜索的开始//在水面上加速器不起作用(!!加速器只能改变垂直速度) dfs( dpth + 1, x + 1, y, tot, 0 );//所以只能靠speedo调速,只能往左 dfs( dpth + 1, x + 1, y + 1, tot, 1 );//或者往下 } else {//表示在水面下 v += p[y][x].acc;//考虑加速度//再考虑speedo的使用(无非就是上、不动、下) dfs( dpth + 1, x + 1, y + v - 1, tot, v - 1 ); dfs( dpth + 1, x + 1, y + v, tot, v ); dfs( dpth + 1, x + 1, y + v + 1, tot, v + 1 ); }}intmain() { int i, j;//计数变量 while ( scanf("%d%d%d", &n, &m, &k), n ) { for ( i = 1; i <= n; i++ ) for ( j = 1; j <= m; j++ ) { scanf("%s", fmt); if ( '$' == *fmt ) { sscanf(fmt, "$%d", &p[i][j].money); p[i][j].acc = 0; } else { sscanf(fmt, "v%d", &p[i][j].acc); p[i][j].money = 0; } }dp[1] = p[1][1].money;//起始位置就赋予该位置的钱数即可for ( i = 2; i <= m; i++ ) dp[i] = -INF;//都初始化为负无穷for ( i = 1; i < m; i++ )//m可以不用搜索,因为它是终点if ( dp[i] > -INF )//如果等于-INF,表示水面上第i列不可达(即不能从水面的前面几列到达该列)//因此从i开始搜索不仅没有意义而且会影响结果的正确性dfs( 0, i, 1, dp[i] - p[1][i].money, 0 );printf("%d\n", dp[m]);//直接输出到达第m列水面的最大钱数,第m列大于1行都是有毒的,游进去会死 } return 0;}
无注释代码:
#include <stdio.h>#define INF 2000001#define MAXN 101#define MAXM 1001#define FMTLEN 20typedef struct { int money; char acc; } Pool;Pool p[MAXN][MAXM];int dp[MAXM];int n, m, k;char fmt[FMTLEN];voiddfs( int dpth, int x, int y, int tot, int v ) { if ( x > m || dpth == k && y > 1 ) return ; if ( y < 1 ) y = 1; else if ( y > n ) y = n; tot += p[y][x].money; if ( dpth && 1 == y ) { if ( tot > dp[x] ) dp[x] = tot; return ; } if ( !dpth ) { dfs( dpth + 1, x + 1, y, tot, 0 ); dfs( dpth + 1, x + 1, y + 1, tot, 1 ); } else { v += p[y][x].acc; dfs( dpth + 1, x + 1, y + v - 1, tot, v - 1 ); dfs( dpth + 1, x + 1, y + v, tot, v ); dfs( dpth + 1, x + 1, y + v + 1, tot, v + 1 ); }}intmain() { int i, j; while ( scanf("%d%d%d", &n, &m, &k), n ) { for ( i = 1; i <= n; i++ ) for ( j = 1; j <= m; j++ ) { scanf("%s", fmt); if ( '$' == *fmt ) { sscanf(fmt, "$%d", &p[i][j].money); p[i][j].acc = 0; } else { sscanf(fmt, "v%d", &p[i][j].acc); p[i][j].money = 0; } } dp[1] = p[1][1].money; for ( i = 2; i <= m; i++ ) dp[i] = -INF; for ( i = 1; i < m; i++ ) if ( dp[i] > -INF ) dfs( 0, i, 1, dp[i] - p[1][i].money, 0 ); printf("%d\n", dp[m]); } return 0;}
- POJ 3827 Facer is learning to swim
- 【DFS】 hdu3260 Facer is learning to swim
- hdu - 3260 - Facer is learning to swim(dfs)
- POJ 3729 Facer’s string
- POJ 3729 Facer’s string
- POJ 3729 Facer’s string (后缀数组)
- POJ-3717-Facer's Chocolate Dream
- POJ 3729 Facer’s string 笔记
- Is functional analysis relevant to machine learning?
- 【English】Learning is about learning how to learn
- POJ 3729 Facer’s string(后缀数组)
- POJ 3729 Facer's string (后缀数组)
- 英语练习77 You ought to learn swim
- 解题报告:HDU_4093 Xavier is Learning to Count FFT
- 《Machine Learning is Fun Part 6: How to do Speech Recognition with Deep Learning》译文
- POJ 3729 Facer’s string (后缀数组 两串后缀的LCP为K的对数)
- IAR中出现 Failed to write memory at 0x866E: SWIM PROG error [42008]: Attempt to write to protected area
- what is machine learning?
- Oanda账户2014重回起点
- Hi3520D SDK 安装以及升级使用说明
- jsoup的基础理论(一)
- POJ 1322 Chocolate
- Windows7 64位和32位有何差异
- POJ 3827 Facer is learning to swim
- 字符设备程序实列二-查询按键值,按键按下相应的LED灯亮,按键松开相应的LED灯灭
- java.util.concurrent包(1)-lock和synchronized对比
- LeetCode —— Sort List
- 虚基类--动物学。。。。
- USB mass storage framework
- NYOJ-60 谁获得了最高奖学金
- Oracle操作XML各种场景介绍
- 用antlr4来实现《按编译原理的思路设计的一个计算器》中的计算器