- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我是计算机科学专业的一年级学生,目前正在参加一些算法竞赛。我编写的以下代码存在一个缺陷,我不确定如何修复
这是问题说明:
http://www.usaco.org/index.php?page=viewproblem2&cpid=811
在声明中,我想念农夫约翰只能在两个靴子都可以站立的瓷砖上切换靴子的地方。我尝试在不同的地方添加约束,但是似乎没有一个可以完全解决该问题。我真的看不出没有屠杀代码的方法
基本上,问题在于John一直在无法站立新靴子的瓷砖上切换靴子,而我似乎无法修复它
这是我的代码(抱歉一个字母的变量):
import java.io.*;
import java.util.*;
public class snowboots {
static int n,k;
static int[] field,a,b; //a,b --> strength, distance
static int pos;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("snowboots.in"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("snowboots.out")));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
k = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
field = new int[n];
a = new int[k];
b = new int[k];
for (int i = 0; i < n; i++)
field[i] = Integer.parseInt(st.nextToken());
for (int i = 0; i < k; i++) {
st = new StringTokenizer(br.readLine());
a[i] = Integer.parseInt(st.nextToken());
b[i] = Integer.parseInt(st.nextToken());
}
pw.println(solve());
pw.close();
}
static int solve() {
pos = 0;
int i = 0; //which boot are we on?
while(pos < n-1) {
while(move(i)); //move with boot i as far as possible
i++; //use the next boot
}
i--;
return i;
}
static boolean move(int c) {
for (int i = pos+b[c]; i > pos; i--) {
if (i < n && field[i] <= a[c]) { //snow has to be less than boot strength
pos = i;
return true;
}
}
return false;
}
}
最佳答案
是的,可以通过添加额外的for
-loop来挽救您的解决方案。
您需要做的是,如果您发现前一双靴子可以一直带到下一个雪地太深的地砖,那么您需要尝试“回溯”到不太合适的最新地砖深。最终给出了在最坏情况下O(N·B)时间和O(1)额外空间的解决方案。
为何回溯到该图块可能还不是很清楚-毕竟,仅仅是因为您可以到达给定的图块,这并不一定意味着您能够在此之前到达所有图块-所以让我解释一下为什么还可以。
令maxReachableTileNum
为您先前启动时可以到达的最后一个图块的编号(1到N之间),令lastTileNumThatsNotTooDeep
为maxReachableTileNum
或之前的最后一个图块的编号(1到N之间),但不要太深下一场雪覆盖。 (我们知道有这样一个图块,因为图块#1根本没有积雪,所以如果没有别的事情,我们知道我们可以追溯到一开始。)现在,由于我们能够到达maxReachableTileNum
,因此可以使用某些引导必须要么踩过lastTileNumThatsNotTooDeep
(在这种情况下,没问题,就可以到达),要么跳过它到以后的某个磁贴(在maxReachableTileNum
上或之前)。但是后面的图块必须比lastTileNumThatsNotTooDeep
更深(因为后面的图块的深度大于s currentBootNum
,后者至少与lastTileNumThatsNotTooDeep
的深度一样大),这意味着跳过lastTileNumThatsNotTooDeep
的启动确实可以踩到lastTileNumThatsNotTooDeep
了:这将意味着比实际覆盖的内容要更短一步(OK)到覆盖较浅的图块(OK)上。因此,无论哪种方式,我们都知道lastTileNumThatsNotTooDeep
是可访问的。因此,对我们来说,回溯到lastTileNumThatsNotTooDeep
是安全的。 (注意:以下代码使用名称reachableTileNum
而不是lastTileNumThatsNotTooDeep
,因为它继续使用reachableTileNum
变量向前搜索以找到可到达的图块。)
但是,我们仍然必须保留以前的maxReachableTileNum
:可能无法进行回溯(因为它可能无法使我们取得比已有的进一步进步),在这种情况下,我们将丢弃这些引导,并且移至下一个对,其上一个值为maxReachableTileNum
。
因此,总的来说,我们有:
public static int solve(
final int[] tileSnowDepths, // tileSnowDepths[0] is f_1
final int[] bootAllowedDepths, // bootAllowedDepths[0] is s_1
final int[] bootAllowedTilesPerStep // bootAllowedTilesPerStep[0] is d_1
) {
final int numTiles = tileSnowDepths.length;
final int numBoots = bootAllowedDepths.length;
assert numBoots == bootAllowedTilesPerStep.length;
int maxReachableTileNum = 1; // can reach tile #1 even without boots
for (int bootNum = 1; bootNum <= numBoots; ++bootNum) {
final int allowedDepth = bootAllowedDepths[bootNum-1];
final int allowedTilesPerStep = bootAllowedTilesPerStep[bootNum-1];
// Find the starting-point for this boot -- ideally the last tile
// reachable so far, but may need to "backtrack" if that tile is too
// deep; see explanation above of why it's safe to assume that we
// can backtrack to the latest not-too-deep tile:
int reachableTileNum = maxReachableTileNum;
while (tileSnowDepths[reachableTileNum-1] > allowedDepth) {
--reachableTileNum;
}
// Now see how far we can go, updating both maxReachableTileNum and
// reachableTileNum when we successfully reach new tiles:
for (int tileNumToTry = maxReachableTileNum + 1;
tileNumToTry <= numTiles
&& tileNumToTry <= reachableTileNum + allowedTilesPerStep;
++tileNumToTry
) {
if (tileSnowDepths[tileNumToTry-1] <= allowedDepth) {
maxReachableTileNum = reachableTileNum = tileNumToTry;
}
}
// If we've made it to the last tile, then yay, we're done:
if (maxReachableTileNum == numTiles) {
return bootNum - 1; // had to discard this many boots to get here
}
}
throw new IllegalArgumentException("Couldn't reach last tile with any boot");
}
2
。)
关于java - 该算法拼图代码(USACO)的良好解决方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54264340/
我尝试理解[c代码 -> 汇编]代码 void node::Check( data & _data1, vector& _data2) { -> push ebp -> mov ebp,esp ->
我需要在当前表单(代码)的上下文中运行文本文件中的代码。其中一项要求是让代码创建新控件并将其添加到当前窗体。 例如,在Form1.cs中: using System.Windows.Forms; ..
我有此 C++ 代码并将其转换为 C# (.net Framework 4) 代码。有没有人给我一些关于 malloc、free 和 sprintf 方法的提示? int monate = ee; d
我的网络服务器代码有问题 #include #include #include #include #include #include #include int
给定以下 html 代码,将列表中的第三个元素(即“美丽”一词)以斜体显示的 CSS 代码是什么?当然,我可以给这个元素一个 id 或一个 class,但 html 代码必须保持不变。谢谢
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我试图制作一个宏来避免重复代码和注释。 我试过这个: #define GrowOnPage(any Page, any Component) Component.Width := Page.Surfa
我正在尝试将我的旧 C++ 代码“翻译”成头条新闻所暗示的 C# 代码。问题是我是 C# 中的新手,并不是所有的东西都像 C++ 中那样。在 C++ 中这些解决方案运行良好,但在 C# 中只是不能。我
在 Windows 10 上工作,R 语言的格式化程序似乎没有在 Visual Studio Code 中完成它的工作。我试过R support for Visual Studio Code和 R-T
我正在处理一些报告(计数),我必须获取不同参数的计数。非常简单但乏味。 一个参数的示例查询: qCountsEmployee = ( "select count(*) from %s wher
最近几天我尝试从 d00m 调试网络错误。我开始用尽想法/线索,我希望其他 SO 用户拥有可能有用的宝贵经验。我希望能够提供所有相关信息,但我个人无法控制服务器环境。 整个事情始于用户注意到我们应用程
我有一个 app.js 文件,其中包含如下 dojo amd 模式代码: require(["dojo/dom", ..], function(dom){ dom.byId('someId').i
我对“-gencode”语句中的“code=sm_X”选项有点困惑。 一个例子:NVCC 编译器选项有什么作用 -gencode arch=compute_13,code=sm_13 嵌入库中? 只有
我为我的表格使用 X-editable 框架。 但是我有一些问题。 $(document).ready(function() { $('.access').editable({
我一直在通过本教程学习 flask/python http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-wo
我想将 Vim 和 EMACS 用于 CNC、G 代码和 M 代码。 Vim 或 EMACS 是否有任何语法或模式来处理这种类型的代码? 最佳答案 一些快速搜索使我找到了 this vim 和 thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve this
这个问题在这里已经有了答案: Enabling markdown highlighting in Vim (5 个回答) 6年前关闭。 当我在 Vim 中编辑包含 Markdown 代码的 READM
我正在 Swift3 iOS 中开发视频应用程序。基本上我必须将视频 Assets 和音频与淡入淡出效果合并为一个并将其保存到 iPhone 画廊。为此,我使用以下方法: private func d
pipeline { agent any stages { stage('Build') { steps { e
我是一名优秀的程序员,十分优秀!