上一篇(https://iobaka.com/blog/87.html)文章解决了该游戏 C 难度下的地区问题,这一篇开始解决难度 B 的问题。
上手
问题1:隔離された街のゲート [MISSION LEVEL: B]
あなたは作りかけのゲームプログラムを発見しましたが、キャラクターの動きの制限する方法が未実装でした。
制作中のゲームは、縦方向に H マスと横方向に W マスだけ広がる格子上のマップを用います。 左下のマスが原点であり、その座標を (0, 0) とします。 原点から横方向に x マス、縦方向に y マス進んだ座標を (x, y) と表記します。
現在の開発段階では障害物などはなく、キャラクターの初期座標が必ず (0, 0) です。 この状態から合計で N 回の上下左右への移動操作が行われます。
各移動操作はキャラクターの座標 (x, y) を以下のように変更します。・上への移動 : キャラクターの座標を (x, y) から (x, y + 1) へ変更する。
・下への移動 : キャラクターの座標を (x, y) から (x, y - 1) へ変更する。
・左への移動 : キャラクターの座標を (x, y) から (x - 1, y) へ変更する。
・右への移動 : キャラクターの座標を (x, y) から (x + 1, y) へ変更する。開発依頼書には、N 回の操作中にキャラクターが不正な座標にいることがないか判定するプログラムの作成が指示されています。
ここで不正な座標とは、マップ外の座標、すなわち格子上に存在しない座標すべてのことを指します。 例えば、入力例 1 および入力例 2 は以下のように考えることができます。
解释:
你发现了一个游戏,但是没有实装限制角色移动的方法。
游戏地图分为纵向 H 和横向 W 的网格状,左下角的格子为原点 (0, 0)
原点横向为 x 轴,纵向为 y 轴,坐标用 (x, y) 表示。
当前开发阶段没有障碍物,角色的起始坐标一定是 (0, 0)。
从原点开始,进行上下左右四个方向的 N 次移动。
开发文档中,需要判定 N 次移动中该角色是否进入了无效坐标。
无效坐标指的是地图外面的坐标,
例如下图。
解答:
这道题判断的是N次移动中,是否出现越界的情况。需要每一步都需要判断是否越界,而不是判断最终位置。
另外要注意的是,到达了负数坐标点也是越界。
所以一样设置一个开关,每一步判断一次,越界就给开关打开,最后输出开关结果就行。
<?php
// 自分の得意な言語で
// Let's チャレンジ!!
$input_lines = fgets(STDIN);
$input_lines = explode(' ', $input_lines);
// 最大 x 和 y 坐标
$max_y = $input_lines[0]-1;
$max_x = $input_lines[1]-1;
// 角色实时坐标
$x = 0;
$y = 0;
$invalid = false;
for ($i = 0; $i < $input_lines[2]; $i++) {
$move = fgets(STDIN);
$move = substr($move, 0, 1);
switch ($move) {
case 'L':
$x--;
if(!check($x, $y, $max_x, $max_y)) $invalid = true;
break;
case 'R':
$x++;
if(!check($x, $y, $max_x, $max_y)) $invalid = true;
break;
case 'U':
$y++;
if(!check($x, $y, $max_x, $max_y)) $invalid = true;
break;
case 'D':
$y--;
if(!check($x, $y, $max_x, $max_y)) $invalid = true;
break;
}
}
if(!$invalid) {
echo 'valid';
}
else {
echo 'invalid';
}
// 检测是否到达无效坐标
function check($x, $y, $max_x, $max_y) {
if($x > $max_x || $y > $max_y || $x < 0 || $y < 0) {
return false;
}
return true;
}
?>
问题2:高層タワー [MISSION LEVEL: B]
単語を組み合わせて新単語を作ります。
新単語は N 個の文字列を、前から順に結合して作ります。
この時、冗長さをなくすため、 前から結合した単語の末尾 と 後ろの単語の先端 が一番長く一致するように結合します。例えば、 入力例 1 の "paiza", "apple", "letter" の場合、 先頭から "paiza", "apple" を条件どおり重ねると "paizapple" となります。 この単語を更に次の単語と重ねると "paizappletter" となります。
なお、必ず前から順番に重ねるため、 入力例 2 の "poh", "p", "oh" を結合する場合は、 "poh" と "p" を重ねた後の単語 "pohp" と "oh" を重ね "pohpoh" となります。
N 個の単語が与えられるので、前から順番に単語を結合した場合の新単語を出力してください。
解释:
通过组合单词来创造一个新的单词。
新单词需要按照顺序组合N个字符串来创造。
此时为了消除冗长部分,组合前后两个字符串时,前一单词末尾和后一单词开头相同的部分需要组合到一起。
例如,输入 "paiza", "apple", "letter" 时,
前两个单词 "paiza", "apple" 需要组合成 "paizapple" 。
这个单词组合后就变成了 "paizappletter" 。
需要注意的是,需要两个两个按照顺序组合,例如输入 "poh", "p", "oh" 时,
"poh" 和 "p" 组合成 "pohp" , 然后和 "oh" 组合成 "pohpoh" 。
给出N个单词,按照顺序组合成一个新单词吧。
解答:
这里我的思路是先创建一个空字符串 S ,把第一个单词放进去,然后之后每个单词都循环判断一下和 S 的相同部分,即如果单词首字母 = S 最后一个字母
,则说明有冗长。继续向前判断,最后剪掉冗长部分,拼接到 S 尾部。
需要注意的是,判断冗长部分不能超出了 S 的长度,比如 S 是 dark, 要组合的单词是 darkgray ,那么 要组合的单词只需要判断前四个字符。
<?php
// 自分の得意な言語で
// Let's チャレンジ!!
$input_lines = fgets(STDIN);
$result = '';
for ($i = 0; $i < $input_lines; $i++) {
$word = fgets(STDIN);
$word = substr($word, 0, strlen($word)-1);
$replace = '';
for ($j = strlen($word); $j > 0; $j--) {
if(strlen($result) >= $j) {
// 是否冗长
if(substr($word, 0, $j) == substr($result, strlen($result)-$j)) {
$replace = substr($word, 0, $j);
break;
}
}
}
// 剪掉冗长字符串
$word = substr_replace($word, "", strpos($word, $replace), strlen($replace));
unset($replace);
// 拼接组合结果
$result = $result.$word;
}
echo $result;
?>
问题3:砂漠の公園 [MISSION LEVEL: B]
昔この公園ではある競技の大会がよく開催されていました。各試合結果の記録が見つかりましたが、どのチームが優勝したかの記録は欠損しています。
そこであなたは各試合結果から優勝チームを調べるプログラムを作成することにしました。大会は勝ち点方式の総当り戦で行います。勝つと2点、引き分けで1点、負けると0点勝ち点が増えます。
すべての試合が終わったあと、勝ち点が一番多いチームが優勝です。大会の参加人数と、試合結果が入力されたときに、何番目のチームが勝ち点いくつの何勝何敗何引き分けで優勝したか出力するプログラムを書いてください。
入力例1を図にすると、以下のようになります。
解释:
这个公园在过去经常举办竞技大会。找到了各种比赛结果的记录,但是缺少了获胜队伍的记录。
所以你要写一个程序,来算出谁是获胜队伍。
比赛结果需要统计每轮得分胜点,胜利得2点,平局得1点,输了则不得点。
比赛结束后,得点最多得队伍则可以获胜。
请编写一个程序,输出获胜得队伍,多少胜点,胜利次数,平局次数,输了得次数。
解答:
又是一道加减法计算题,先定义一个获胜队伍的数据为0,然后每个队伍循环和获胜队伍比较,比当前获胜队伍的得点高就把该队伍数据放入获胜队伍数据里,最后输出出来获胜队伍数据即可。
这道题感觉难度为 C 会比较合理一些。
<?php
// 自分の得意な言語で
// Let's チャレンジ!!
$max_team = 0;
$max_score = 0;
$max_w = 0;
$max_d = 0;
$max_l = 0;
$input_lines = fgets(STDIN);
$team = [];
for ($i = 0; $i < $input_lines; $i++) {
$data = fgets(STDIN);
$w = 0;
$d = 0;
$l = 0;
$score = 0;
for ($j = 0; $j < strlen($data); $j++) {
$key = substr($data, $j, 1);
switch ($key) {
case 'W':
$score = $score + 2;
$w++;
break;
case 'D':
$score = $score + 1;
$d++;
break;
case 'L':
$l++;
break;
}
}
if($score >= $max_score) {
$max_team = $i+1;
$max_score = $score;
$max_w = $w;
$max_d = $d;
$max_l = $l;
}
}
echo $max_team.' '.$max_score.' '.$max_w.' '.$max_d.' '.$max_l;
?>
结尾
这样一来,就剩下难度A的题目了。