2017年藍橋杯省賽JavaB組——包子湊數(序列型動態規劃)

題目描述:

小明幾乎天天早晨都會在一家包子鋪吃早餐。他發現這家包子鋪有 NNN 種蒸籠,其中第 iii 種蒸籠剛好能放 Ai個包子。每種蒸籠都有很是多籠,能夠認爲是無限籠。java

每當有顧客想買 X 個包子,賣包子的大叔就會迅速選出若干籠包子來,使得這若干籠中剛好一共有 X 個包子。好比一共有 3 種蒸籠,分別能放 三、4 和 5 個包子。當顧客想買 11 個包子時,大叔就會選 2 籠 3 個的再加 1 籠 5 個的(也可能選出 1 籠 3 個的再加 2 籠 4 個的)。算法

固然有時包子大叔不管如何也湊不出顧客想買的數量。好比一共有 3 種蒸籠,分別能放 四、5 和 6 個包子。而顧客想買 7 個包子時,大叔就湊不出來了。學習

小明想知道一共有多少種數目是包子大叔湊不出來的。spa

輸入描述

第一行包含一個整數 N (1≤N≤100)。code

如下 N 行每行包含一個整數 Ai​ (1≤Ai≤100)。視頻

輸出描述

一個整數表明答案。若是湊不出的數目有無限多個,輸出 INF。blog

 

輸入輸出樣例

示例 1內存

輸入class

2
4
5

輸出import

6
樣例說明

湊不出的數目包括:1, 2, 3, 6, 7, 11。

示例 2

輸入

2
4
6

輸出

INF

全部奇數都湊不出來,因此有無限多個

運行限制

  • 最大運行時間:1s
  • 最大運行內存: 256M

 

思路:動態規劃

這一題其實一開始在我沒有聽侯衛東老師將的動態規劃視頻時,我根本就不會這類動態規劃問題,就連其基本思路都不清楚,就是根據本身的想法寫的,沒有一點算法思想在裏面,並且最後還超時了哈哈。當時就在想,若是一碰到動態規劃題目就不會,那麼怎麼去比賽,因此就下定決心去b站上找關於動態規劃算法的相關視頻,看看能不能學習一下大佬的思惟,畢竟算法是前人通過很長時間苦心研究出來的,僅憑沒有一點經驗的我怎麼可能在這麼短的時間研究透,後面學習了侯老師的一些動態規劃算法的一點點解題技巧後,再來作這題,沒想到居然真的AC了,太難以想象了。不得不說動態規劃算法真的太強了,不只時間複雜度低,並且代碼還很簡潔,就很nice,本身對動態規劃算法也逐漸有點興趣了。要知道興趣是最好的導師,加油,沒有什麼是努力一天不能作到的(這裏開個玩笑哈,其實我是一個菜狗),若是不行那就再努力一天。

 

AC代碼:

 1 import java.util.Scanner;
 2 // 1:無需package
 3 // 2: 類名必須Main, 不可修改
 4 
 5 public class Main {
 6     public static void main(String[] args) {
 7         Scanner scan = new Scanner(System.in);
 8         //在此輸入您的代碼...
 9         int n = scan.nextInt();
10         int[] buns = new int[n];
11         for (int i = 0; i < n; i++) {
12           buns[i] = scan.nextInt();
13         }
14         
15         scan.close();
16 
17         System.out.println(f(buns));
18     }
19 
20     public static String f(int[] buns) {
21       if (buns == null || buns.length == 0) {
22         return "INF";
23       }
24 
25       int n = 100000;
26       // 定義狀態:dp[i] 表示i個包子是否能湊出來
27       boolean[] dp = new boolean[n + 1];
28 
29       // 初始化
30       dp[0] = true;
31 
32       // 轉移方程
33       for (int i = 1; i <= n; i++) {
34         // 默認湊不出來
35         dp[i] = false;
36         for (int j = 0; j < buns.length; j++) {
37           if (i >= buns[j] && dp[i - buns[j]]) {
38             dp[i] = true;
39           }
40         }
41       }
42 
43       // 找到最小的包子數
44       int minv = Integer.MAX_VALUE;
45       for (int i = 0; i < buns.length; i++) {
46         minv = Math.min(minv, buns[i]);
47       }
48 
49       int count = 0;
50       int total = 0;
51       boolean flag = false;
52       // 返回結果
53       for (int i = 1 ; i <= n; i++) {
54         if (dp[i]) {
55           count++;
56           if (count == minv) {
57             flag =  true;
58             break;
59           }
60         } else {
61           total++;
62           count = 0;
63         }
64       }
65 
66       if (flag) {
67         return total + "";
68       } else {
69         return "INF";
70       }
71     }
72 }
相關文章
相關標籤/搜索