標籤:動態規劃 c++ 裝配線
這幾天一直再看,覺得看懂了一些,先記下來。
動態規劃
動態規劃是運籌學的一個方向,就是把多級最佳化問題分解成一系列的單階問題。在不斷增加的過程中,不斷的計算當前問題的最優解。
一般分為如下四個部分:
- 線性動規:攔截飛彈,合唱隊形,挖地雷,建學校,劍客決鬥等;
- 地區動規:石子合并, 加分二叉樹,統計單詞個數,炮兵布陣等;
- 樹形動規:貪吃的九頭龍,二分尋找樹,聚會的歡樂,數字三角形等;
- 背包問題:01背包問題,完全背包問題,分組背包問題,二維背包,裝箱問題,擠牛奶(同濟ACM第1132題)等;
汽車生產線問題
這個問題是《演算法導論》的動態規劃的例題,我自己覺得這道題比較簡單而且典型,所以就解釋下這個題目:
Colonel汽車公司在有兩條裝配線的工廠裡產生汽車。每一條裝配線上有n個裝配站,
兩條生產線上相同位置的裝配站功能相同,但所需時間不同,並且汽車底盤在兩條
裝配線間轉移要花費一定的時間。如所示兩條生產線。
首先我們知道每個階段的最短時間,都包含了上一階段的最短時間。
而比較簡單的是,我們只有兩種情況,一種是在裝配線1上時間短,一種是在裝配線2上時間短。
假如暴力搜尋,貪心去算得話(也就是遞迴的辦法)。時間複雜就是2^n,這個是不可接受的。
這個時候我們的辦法是先從第一個問題開始,裝配線1, 2上只有一個station。那麼比較簡單,一比較就好了。當有兩個station的時候,就是從上一次比較的結果中(一個line 1最短,一個line 2最短)中繼續加上當前station的值繼續比較。
所以我們發現是每個當前的最優解,都包含了上一次的最優解。
代碼
代碼就是我們從最開始,一直儲存當前問題的最優解,然後去求的下一次的最優解。
//// main.cpp// DP_line//// Created by Alps on 15/4/26.// Copyright (c) 2015年 chen. All rights reserved.//#include <iostream>using namespace std;#define NUM 5int main(){ int first[NUM];//到裝備站1,i的最短路徑長度 int second[NUM];//到裝配站2,i的最短路徑長度 int linef[NUM]; //從1進入的路徑 int lines[NUM]; //從2進入的路徑 int a[NUM]; //在裝配站1,i 所需要呆的時間 int b[NUM]; //再裝配站2,i 所需要呆的時間 int m[NUM]; //從裝配站1,i-1 到裝配站2,i的時間 int n[NUM]; //從裝配站2,i-1 到裝配站1,i的時間 int line[NUM]; //當前最短路經所經過的裝配站 int f[NUM]; //當前最短路徑長度 int ea,eb,xa,xb; // ea為進入裝配站1時間,eb為進入2的時間,xa為出裝配站1的時間,xb為出裝配站2的 scanf("%d %d %d %d",&ea,&eb,&xa,&xb); for(int i=0;i<NUM;++i) { scanf("%d %d", &a[i], &b[i]); } first[0] = ea + a[0]; second[0] = eb + b[0]; for(int i=0;i<NUM-1;++i) { scanf("%d %d", &m[i], &n[i]); } for(int i=1;i<NUM;++i) { if(first[i-1] + a[i] < second[i-1] + m[i-1] + a[i]) { first[i] = first[i-1] + a[i]; linef[i] = 1; }else{ first[i] = second[i-1] + m[i-1] + a[i]; linef[i] = 2; } if(second[i-1] + b[i] < first[i-1] + n[i-1] + b[i]) { second[i] = second[i-1] + b[i]; lines[i] = 2; }else { second[i] = first[i-1] + n[i-1] + b[i-1]; lines[i] = 1; } } for(int i=0;i<NUM;++i) { if(first[i] + xa < second[i] + xb) { f[i] = first[i] + xa; line[i] = 1; }else{ f[i] = second[i] + xb; line[i] = 2; } } for(int i=0;i<NUM;++i) { printf("station %d\n",line[i]); } printf("Distince is %d\n",f[NUM-1]); return 0;}
這個代碼比較簡單,精華就是那個for迴圈了。
測試案例如下:
3 2 3 44 33 66 32 35 22 32 43 44 3
假如有任何建議,歡迎評論。互相學習。謝謝。
演算法學習 - 動態規劃(DP問題)(C++)