面試中的動態規劃問題

三個例子

由於最近參加公司的筆試面試,發現遇到的動態規劃問題實在是多,在這邊博客裏,我特地將一些經典的算法例子抽取出來,想必之後在遇到這種動態規劃的時候都可以找到合適的模板,進行快速解題。在實戰之中,最難把握的就是通項公式的推導,我推薦在面試中遇到此類題目,優先採用遞歸的思路求解。

例1:

n(10>=n>=1)種商品A1,A2,...,An,每種商品數量分別爲a1,a2,...,an個,記做{a1,a2,...,an}(ak>0)。熱門組合商品會進行預包裝。假設這n個商品有m(9>=m>=1)個商品組合,每個組合bomk包含A1,A2,...,An的數量分別爲{b1,b2,...,bn}(bk>=0,至少存在一個bk>0)

舉例如下:

訂單包含A,B,C商品,數量爲{231},商品組合bom1{211},bom2{110},bom3{011}

對以上訂單匹配給定商品組合,得到的可能匹配結果爲:res1.匹配到組合1一套,剩餘B商品;res2.匹配到組合2兩套,組合3一套,不剩商品;

現要求訂單的最優匹配,最優匹配的原則爲:1.匹配組合後,剩餘商品種類數越少越好;2.在剩餘商品種類數相同的情況下,匹配到的組合種類數越少越好;

例如上面例子,我們認爲res2優於res1。



現需要編寫程序,輸入格式爲:

n,m

a1,a2,...,an

bom1,b11,b12,...,b1n

bom2,b21,b22,...,b2n

....

bomm,bm1,bm2,...,bmn



輸入數據的格式說明(數據間使用英文逗號分隔):

第一行數據:n個商品,m個預包方案

第二行數據:商品1個數,商品2個數,。。。,商品n個數

第三行數據:bom1,商品1個數,商品2個數,。。。,商品n個數

第n-1行數據:。。。。

第n行數據:bomn,商品1個數,商品2個數,。。。,商品n個數



針對輸入數據找出最優匹配,輸出最優匹配的組合及套數,比如針對上面的例子輸出:

match result:

bom2*2,bom3*1

注:輸出結果有多個時可以亂序
import copy
input_data1=input().split(',')
m = [int(x) for x in input_data1][0]
n = [int(x) for x in input_data1][1]
input_data2 = input().split(",")
limit = [int(x) for x in input_data2]
boms = []
for i in range(n):
    input_temp = input().split(',')
    boms.append([int(x) for x in input_temp])

best_combo = [0]*n
best_num = [0]*m
current_bag = [0]*n
bag_num = [0]*m

def bag(current_bag,bag_num):
    global best_combo
    global best_num
    temp_num = -1
    for bom in boms:
        new_current_bag = copy.deepcopy(current_bag)
        new_bag_num = copy.deepcopy(bag_num)
        temp_num += 1
        temp_flag = True
        for i in range(n):
            if current_bag[i] + bom[i] > limit[i]:  #判斷n件商品是否能全部放入揹包
                temp_flag = False
        if temp_flag:              #如果能夠全部放入揹包則全部放入揹包如一個物品可以被加入
            new_bag_num[temp_num] += 1
            for j in range(n):
                new_current_bag[j] += bom[j]
            if better_than(new_current_bag,new_bag_num,best_combo,best_num):
                best_combo = current_bag
                best_num = bag_num
            bag(new_current_bag,new_bag_num)


def better_than(current_bag,bag_num,best_combo,best_num):
    if (sum([(limit[i]-current_bag[i]) for i in range(n)]) < sum([(limit[i]-best_combo[i]) for i in range(n)])):  #如果剩餘的總量小,則最好的揹包是現在的揹包
        return True
    elif sum([(limit[i]-current_bag[i]) for i in range(n)]) == sum([(limit[i]-best_combo[i]) for i in range(n)]): #如果剩餘的總量相等,比較種類數量
        if sum(bag_num) < sum(best_num):
            return True

bag(current_bag,bag_num)

例2

找零錢問題:

有一個數組changes,changes中所有的值都爲正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,對於一個給定值x,請設計一個高效算法,計算組成這個值的方案數。

給定一個int數組changes,代表所以零錢,同時給定它的大小n,另外給定一個正整數x,請返回組成x的方案數,保證n小於等於100且x小於等於10000。

測試樣例:
[5,10,25,1],4,15
返回:6
測試樣例:
[5,10,25,1],4,0
返回:1


//這道題目有兩種實現方式,分別是遞歸以及非遞歸,這裏優先寫出遞歸的模式
public static int solusion(int[] array,int begin,int end,int target){
    //返回條件
    if (target == 0){
        return 1;
    }
    if(begin > end){
        return 0;
    }
    int count = 0;
    int times = 0;
    for(times*array[begin] <= target){
        count+=solustion(array,begin+1,end,target-times*array[begin]);
        times++;
    }
    return count;
}
//以下代碼是迭代實現的案例:
public static int solusion(int[] array,int m,int n){
//初始化工作
    int[] dp = new int[n+1];
    dp[0]=1;
    for(int charge:array){
        for(int i=0;i+charge <= target;i++){
            dp[i+charge] += dp[i]
            }
        }
    return dp[n]


    }

例3

全排列問題:

輸入一個字符列表,輸出他的全排列(改:排列中不得出現重複的排列)

package Test;

import java.util.Arrays;

public class Test4 {


    public static void allpossible(int[] array,int begin) {
        int temp;
        int end = array.length;
        if(begin==end) {
            System.out.println(Arrays.toString(array));
            return;
        }
        else

        for(int x=begin;x<end;++x) {
            //swap index to all data;
            temp = array[begin];
            array[begin] = array[x];
            array[x] = temp;
            allpossible(array, begin+1);
            temp = array[begin];
            array[begin] = array[x];
            array[x] = temp;
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int [] test = {3,2,1};
        allpossible(test, 0);

    }

}
package Test;

import java.util.Arrays;
import java.util.HashSet;

public class Test5 {


    public static void allpossible(int[] array,int begin) {
        HashSet<int[]> testSet = new HashSet<int[]>();
        int temp;
        int end = array.length;
        if(begin==end) {
            if(!testSet.contains(array)) {
                testSet.add(array);
                System.out.println(Arrays.toString(array));
            }
            return;
        }
        else

        for(int x=begin;x<end;++x) {
            //swap index to all data;
            temp = array[begin];
            array[begin] = array[x];
            array[x] = temp;
            allpossible(array, begin+1);
            temp = array[begin];
            array[begin] = array[x];
            array[x] = temp;
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int [] test = {3,2,2,1};
        allpossible(test, 0);

    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章