1. 程式人生 > >動態規劃 硬幣 POJ

動態規劃 硬幣 POJ

總時間限制: 1000ms 記憶體限制: 262144kB
描述
宇航員Bob有一天來到火星上,他有收集硬幣的習慣。於是他將火星上所有面值的硬幣都收集起來了,一共有n種,每種只有一個:面值分別為a1,a2… an。 Bob在機場看到了一個特別喜歡的禮物,想買來送給朋友Alice,這個禮物的價格是X元。Bob很想知道為了買這個禮物他的哪些硬幣是必須被使用的,即Bob必須放棄收集好的哪些硬幣種類。飛機場不提供找零,只接受恰好X元。
輸入
第一行包含兩個正整數n和x。(1 <= n <= 200, 1 <= x <= 10000)
第二行從小到大為n個正整數a1, a2, a3 … an (1 <= ai <= x)
輸出
第一行是一個整數,即有多少種硬幣是必須被使用的。
第二行是這些必須使用的硬幣的面值(從小到大排列)。

樣例輸入
5 18
1 2 3 5 10

樣例輸出
2
5 10

本篇文章收錄了兩種不同的程式碼思路

分別來自@BeiYu-oi和@iamxym

說是兩種不同程式碼,其實整體的核心思路相同.不過是一個完全採用了動規的實現方法,另一個結合了遞迴;

核心思路:首先求出所有硬幣組合成總價值為j的方法總數(0 <= p <= x);然後考慮遞推關係式,遍歷每一個硬幣,如果硬幣必須被使用,則總價值為x的方法中,每一種都含有這個硬幣,若這個硬幣的價值為i,則總價值為x的組合方法中,不含有這個硬幣的方法數目為0;總價值為x - i的組合方法中,含有這個硬幣的方法數目也為0;這兩個判斷條件任選其一;

如何求出所有硬幣組合成總價值為i的方法總數呢?

開陣列kinds[10010],下標為總價值;

每一次輸入一個硬幣就更新一次kinds陣列,輸入硬幣後kinds[j] 有兩種選擇:不含有這個硬幣和含有;對於不含有的方法總數等於輸入硬幣前的kinds[j],含有這個硬幣大的方法數目等於輸入硬幣前的kinds[j - value](value為輸入硬幣的面值)

既然每次更新kinds[j]都要用到更新前的kinds[j - value],那就從後向前更新;

話不多說,上程式碼!

方法一:來自@BeiYu-oi

/*
 *  程式名: 硬幣
 *    作者: transient_arold
 *    時間: 2017/5/31
 *
 *
 */ #include<iostream>
#include<cstring>
#include<algorithm> using namespace std; int kinds[10010]; // 儲存總價值為p的方法總數; int calc(int allvalue, int nowvalue) // 總價值為allvalue
           //不含有這一枚面值為nowvalue的硬幣的方法數目;
{
 if (allvalue < 0)
  return 0;
 else
  return kinds[allvalue] - calc(allvalue - nowvalue, nowvalue);//總方法數減去含有這一枚面值為nowvalue的硬幣的方法數目;
                                                                  //即減去總價值為allvalue - nowvalue,不含這枚硬幣的方法數目;
}
int main()
{
 int n, x; // n是硬幣總數,x是要湊成的總面值;
 cin >> n >> x;
 int values[210]; // 儲存每一個硬幣的面值;
 kinds[0] = 1;// 初始條件,總面值為0的方法為1;  for (int i = 1; i <= n; ++i)
 {
  cin >> values[i];   /*每輸入一枚硬幣就更新一次kinds*/
  for (int j = x; j >= values[i]; --j)
   kinds[j] += kinds[j - values[i]];
 }  int finalcoin[210];
 int cntcoin = 0;  /*遍歷每一枚硬幣,
        若總價值為x且不含這枚硬幣的方法數目為0,則必須含有這枚硬幣*/
  for (int i = 1; i <= n; ++i)
   if (calc(x, values[i]) == 0)
    finalcoin[cntcoin++] = values[i];
  cout << cntcoin << endl;
  if (!cntcoin)
   cout << endl;
  else
   for (int i = 0; i < cntcoin; ++i)
    cout << finalcoin[i] << " ";
  return 0;
} 方法二,來自@iamxym /*
 * 硬幣 方法二
 * 作者:hp
 * 時間:2017/5/30 19:50:46
 *
 */ #include <iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int kinds[10010]; // 總價值為j的硬幣組合種數
int mykinds[10010]; // 每輸入一次硬幣更新一次
                    // 表示不含這個硬幣,價值為j的硬幣組合種數目
                    //若mykinds[x]為0,則必須包含這一枚硬幣 int number[210];//必須包含的硬幣,其中num[0]表示必須包含的硬幣數目; int main()
{
 int n, x;
 cin >> n >> x;
 int values[210]; // 表示每一個硬幣的面值
 kinds[0] = 1;  /*輸入硬幣並計算kinds[j]*/
 for (int i = 1; i <= n; ++i)
 {
  cin >> values[i];
 
  /*計算有i個硬幣時的kinds[j]*/
  for (int j = x; j >= values[i]; --j)
   kinds[j] += kinds[j - values[i]];
 }  /*逐個檢視每一個硬幣是不是必須的*/
 for (int i = 1; i <= n; ++i)
 {
  memset(mykinds, 0, sizeof(mykinds));
  mykinds[0] = 1;
  for (int j = 1; j <= x; ++j)
   if (j >= values[i])
   mykinds[j] = kinds[j] - mykinds[j - values[i]];
   else
    mykinds[j] = kinds[j];   if (mykinds[x] == 0)
   number[++number[0]] = values[i];
 }
 cout << number[0] << endl;
 if (number[0] == 0)
  cout << endl;
 else {
  sort(number + 1, number + number[0]);
  for (int i = 1; i <= number[0]; i++)
   cout << number[i] << " ";
 }
 return 0;
} 希望對大家有所幫助,也歡迎朋友們指出不足,提出問題,或給出更優演算法,謝謝!

相關推薦

動態規劃 硬幣 POJ

總時間限制: 1000ms 記憶體限制: 262144kB 描述 宇航員Bob有一天來到火星上,他有收集硬幣的習慣。於是他將火星上所有面值的硬幣都收集起來了,一共有n種,每種只有一個:面值分別為a1,a2… an。 Bob在機場看到了一個特別喜歡的禮物,想買來送給朋友Alice,這個禮物的價格是X元。B

動態規劃——硬幣找零

max 關系 i++ 是否 coin fine 個數 names std   動態規劃問題,主要在於需要想清楚遞推關系,num[i][j]表示能使用 i 種硬幣時,得到 j 零錢的最優解。   想來就是首先假設只能使用第一種硬幣 1 ,那麽會得到num[ 1 : n] =

動態規劃-硬幣找零問題四種情況

題目1:給定陣列arr,arr中所有的值都是正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim代表要找的錢數,求組成aim的最少貨幣數。 舉例:  arr[5,2,3],aim=20。  4張5元可以組成20元,其他的找錢方案都要使

動態規劃 硬幣問題,求最大、最小可以組成一個錢數的數

核心思想:         在我們從 1 元開始依次找零時,可以嘗試一下當前要找零的面值(這裡指 1 元)是否能夠被分解成另一個已求解的面值的找零需要的硬幣個數再加上這一堆硬幣中的某個面值之和,如果這樣分解之後最終的硬幣數是最少的,

動態規劃-硬幣問題

有n種硬幣,面值分別為V1,V2,....,Vn,每種都有無限多。給定非負整數S,可以選用多少個硬幣,使得面值之和恰好為S?輸出硬幣數目的最小值和最大值。 1<=n<=100 0<=S<=10000 1<=Vi<=S 輸入:硬幣的種類n,

動態規劃】[POJ 1050]To the Max

就是最大矩陣和,如果直接爆搜複雜度就是O(n4)的所以進行優化,sum[i][j][k]表示在第i列到第j列的第k行的和,那麼就列舉i, j然後最大子段和,然後就變成O(n3)了, 反正n只有100就過

動態規劃-硬幣組合數目

import java.util.Scanner; /* * 硬幣的型別有1角,2角,5角,給定一個數額n,多少種組合方式 */ //暴力解法 public class CashNum {

動態規劃-硬幣組合

1.問題描述        對於m個面值為v1,v2,vm的硬幣,組成錢數n,不限制硬幣的數量和位置,求這些硬幣,最多有多少種組合的結果剛好等於n。2.分析     n=x1*v1+x2*v2+....+xm*vm,{x1,x2,....,xm}就是其中的一種組合,定義l[i

100道動態規劃——27 POJ 1185 炮兵陣地 狀態壓縮,預處理,滾動陣列

        不是很會狀態壓縮,學習一個         定義狀態dp[row][i][j]表示當前考慮第row行,該行狀態為i且上一行狀態為j時可安放的最大炮兵數目         狀態轉移方程就是dp[row][i][j]=max(dp[row][i][j],dp[r

動態規劃——硬幣問題

package dynamic_programming; /** * @author Tom Qian * @email [email protected] * @github https://github.com/bluemaplema

動態規劃】[POJ 1088]滑雪

意思就是把所有點存下來,按照高度排個序, 然後從小到大列舉,然後判斷當前的點的四個方向有沒有存在經過當前點更優的情況,並且那個點的高度比當前點的高度要高如果存在就更新,因為根據大小排了序,所以不會出現不會出現一個點重複統計的情況那麼複雜度是O(n2) #inc

動態規劃-硬幣問題分析

什麼是動態規劃 上次對動態規劃已經有了個大概的分析。引用維基百科的話就是: dynamic programming is a me

poj 動態規劃專題練習

b+ 結點 練習 不難 loading get 初始 cas 動態 http://poj.org/problem?id=2336 大意是要求一艘船將m個車運到對岸所消耗的最短時間和最小次數 定義dp[i][j]運送前i個車,當前船上有j個車所消耗的時間,非常容易得到如下ac

洛谷P1450 [HAOI2008]硬幣購物 動態規劃 + 容斥原理

string -1 line sum mes 開始 clas 完全背包 預處理 洛谷P1450 [HAOI2008]硬幣購物 動態規劃 + 容斥原理 1、首先我們去掉限制 假設 能夠取 無數次 也就是說一開始把他當做完全背包來考慮 離線DP 預處理 復雜度 4*v

poj 3267 The Cow Lexicon (動態規劃)

input mil sys 裏的 single ont n-1 ret map The Cow Lexicon Time Limit: 2000MS Memory Limit: 65536K Total Submissio

poj 3744 Scout (Another) YYF I - 概率與期望 - 動態規劃 - 矩陣快速冪

遞推 cto bits dig min ability 構建 nes text (Another) YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate int

動態規劃_百煉4120 硬幣

amp 使用 兩種 部分 新的 tor color 不能 blog 1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <math.h> 4 #includ

poj 2385【動態規劃

ostream bmi 。。 set row include urn get 定義 poj 2385 Apple Catching Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1400

java動態規劃硬幣問題

四種 ava exti 千萬 print light sca 小數 length 最近一直在研究動態規劃的問題。今天遇到了取硬幣問題。 其實動態規劃還是,我從底部向頂部,依次求出每個狀態的最小值,然後就可以標記上。 這道題目就是,假如有1,5,7,10這四種幣值的硬幣,我取

POJ-1458 LCS(線性動態規劃

cstring turn sizeof namespace ret div algo 動態 std 此題經典線性動態規劃。 代碼如下: #include<iostream> #include<cstdio> #include<cstdlib&