巧用记忆化搜索代替暴力递归(洛谷P1464题题解,Java语言描述)
題目要求
P1464題目鏈接
分析
如果……你信了這題干,真的寫了遞歸……TLE警告!!!
所以,就需要優(yōu)化嘛……
[?9223372036854775808,9223372036854775807]這個(gè)范圍,就是C的longlong / Java的long誒,算是一種數(shù)很大但還有良心的提示吧。
這題比較適合記憶化搜索,這也是我第一次寫記憶化搜索的題解誒,就扯一扯……
一般說來,動(dòng)態(tài)規(guī)劃總要遍歷所有的狀態(tài),而搜索可以排除一些無效狀態(tài)。更重要的是搜索還可以剪枝,可能剪去大量不必要的狀態(tài),因此在空間開銷上往往比動(dòng)態(tài)規(guī)劃要低很多。記憶化算法在求解的時(shí)候還是按著自頂向下的順序,但是每求解一個(gè)狀態(tài),就將它的解保存下來,以后再次遇到這個(gè)狀態(tài)的時(shí)候,就不必重新求解了。這種方法綜合了搜索和動(dòng)態(tài)規(guī)劃兩方面的優(yōu)點(diǎn),因而還是很有實(shí)用價(jià)值的。
對(duì)于本題的話,只要一個(gè)記憶化儲(chǔ)存就可以避免大量運(yùn)算量(大佬們都說這玩意和遞推/動(dòng)態(tài)規(guī)劃差不多)。
主要思路就是開一個(gè)三維數(shù)組,把每一個(gè)“w”函數(shù)的值儲(chǔ)存起來,下一次就可以直接調(diào)用,節(jié)省大量時(shí)間。
使用的時(shí)候還要先想,記憶化的數(shù)組要開多大。對(duì)于這個(gè)題來說,輸入數(shù)據(jù)在long(Java)范圍內(nèi),對(duì)于每一組a,b,c都使用一個(gè)變量來進(jìn)行記憶化是不現(xiàn)實(shí)的。
但是,根據(jù)題意,當(dāng)a<0 or b<0 or c<0時(shí),返回值都是1,當(dāng)a>20 or b>20 or c>20時(shí),返回值都是w(20,20,20),因此,對(duì)于以上的這些數(shù)據(jù),我們可以不進(jìn)行記憶化處理。
所以, long[25][25][25] 就可以了……
輸出注意空格!!!我因此白白WA一次,真悲催啊~~
AC代碼(Java語言描述)
import java.util.ArrayList; import java.util.List; import java.util.Scanner;public class Main {private static long[][][] array = new long[25][25][25];private static long w(int a, int b, int c) {if(a <= 0 || b <= 0 || c <= 0) {return 1;}if(a > 20 || b > 20 || c > 20) {return w(20, 20, 20);}if(a < b && b < c) {if(array[a][b][c-1] == 0) {array[a][b][c-1] = w(a, b, c-1);}if(array[a][b-1][c-1] == 0) {array[a][b-1][c-1] = w(a, b-1 ,c-1);}if(array[a][b-1][c] == 0) {array[a][b-1][c] = w(a, b-1, c);}array[a][b][c] = array[a][b][c-1] + array[a][b-1][c-1] - array[a][b-1][c];} else {if(array[a-1][b][c] == 0) {array[a-1][b][c] = w(a-1, b, c);}if(array[a-1][b-1][c] == 0) {array[a-1][b-1][c] = w(a-1, b-1 ,c);}if(array[a-1][b][c-1] == 0) {array[a-1][b][c-1] = w(a-1, b, c-1);}if(array[a-1][b-1][c-1] == 0) {array[a-1][b-1][c-1] = w(a-1, b-1, c-1);}array[a][b][c] = array[a-1][b][c] + array[a-1][b][c-1] + array[a-1][b-1][c] - array[a-1][b-1][c-1];}return array[a][b][c];}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String endFlag = "-1 -1 -1";List<StringBuilder> list = new ArrayList<>();while (true) {String temp = scanner.nextLine();if (endFlag.equals(temp)) {break;}StringBuilder builder = new StringBuilder();String[] nums = temp.split("\\s+");int a = Integer.parseInt(nums[0]), b = Integer.parseInt(nums[1]), c = Integer.parseInt(nums[2]);builder.append("w(").append(a).append(", ").append(b).append(", ").append(c).append(") = ").append(w(a,b,c));list.add(builder);}scanner.close();for (StringBuilder s : list) {System.out.println(s);}}}總結(jié)
以上是生活随笔為你收集整理的巧用记忆化搜索代替暴力递归(洛谷P1464题题解,Java语言描述)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Python】Numpy中对向量、矩阵
- 下一篇: 【Java】Eclipse输入命令行参数