假設你想以最美觀的方式佈置花店的櫥窗。如今你有F束不一樣品種的花束,同時你也有至少一樣數量的花瓶(V>=F)被按順序擺成一行。這些花瓶的位置固定於架子上,並從1至V順序編號,V是花瓶的數目,從左至右排列,則最左邊的是花瓶1,最右邊的是花瓶V。花束能夠移動,而且每束花用1至F間的整數惟一標識。標識花束的整數決定了花束在花瓶中的順序,若是I<J,則令花束I必須放在花束J左邊的花瓶中。
例如,假設一束杜鵑花的標識數爲1,一束秋海棠的標識數爲2,一束康乃馨的標識數爲3,全部的花束在放入花瓶時必須保持其標識數的順序,即:杜鵑花必須放在秋海棠左邊的花瓶中,秋海棠必須放在康乃馨左邊的花瓶中。若是花瓶的數目大於花束的數目。則多餘的花瓶必須空置,且每一個花瓶中只能放一束花.每個花瓶都具備各自的特色。所以,當各個花瓶中放入不一樣的花束時,會產生不一樣的美學效果,並以美學值(一個整數)來表示,空置花瓶的美學值爲零。在上述例子中,花瓶與花束的不一樣搭配所具備的美學值,以下表所示。java
花瓶 | ||||||
1 | 2 | 3 | 4 | 5 | ||
花束 | 1(杜鵑花) | 7 | 23 | -5 | -24 | 16 |
2(秋海棠) | 5 | 21 | -4 | 10 | 23 | |
3(康乃馨) | -21 | 5 | -4 | -20 | 20 |
根據上表,杜鵑花放在花瓶2中,會顯得很是好看;但若放在花瓶4中則顯得十分難看。爲取得最佳美學效果,你必須在保持花束順序的前提下,使花束的擺放取得最大的美學值。若是有不止一種的擺放方式具備最大的美學值,則其中任何一種擺放方式均可以接受,但你只要輸出任意一種擺放方式。算法
若是已知那些須要放到花瓶裏,那些不須要放。那麼再將這些花束按照順序擺放,找到最優擺放方式。當已知這個花束放不放時,後面就能夠用DP思想填表完成。咱們用編碼的方式表示這束花會不會擺放。0表示不放,1表示放。由於編碼的最後一位比較好獲得,因此咱們先安排最靠右邊的花(當這個花須要擺放時),意思就是先填表的最下一行:(初始值)
dp[i][j]=b[i][j],這個花束被放而且在最右邊的花瓶中
用dp[i][j]表示第i個花束放在花瓶j中(在(i+1...F)已經放置狀況下)的最大值。則狀態轉移方程:
dp[i][j]=b[i][j]+max {dp[i+1][m],m in (j+1,n),j in(0,n-num)}
而後對於每個編碼重複這個填表過程最終求得最大值this
public static void getMax(int[][] b,int F,int V) { class Point{ int x; int y; public Point(int x, int y) { this.x = x; this.y = y; } } int n=(1<<F);//得到編碼個數 int[][]dp=new int[F][V]; Point[][] p=null; //Map<Integer,Point[][]> map=new HashMap<Integer,Point[][]>();//保存最優路徑,key:編碼對應的十進制數 int x=0,mmax=0,ms=0,me=0;//mmax指最大值全部分數中的最大值,ms、me爲最大值對應行和列 while(x!=n) { int num=0,index=0,max=0,temp=x,col=0;//num表示是否是初值,max記錄當前編碼下的最大值,由於有可能隔行填表,index記錄上一次填表的行數,temp表示對x進行移位操做 Point[][]path=new Point[F][V];//保存最優值 for(int i=F-1;i>=0;i--) { if((temp&1)==1) {//這束花被放 if(num==0) { for(int j=0;j<V;j++) { dp[i][j]=b[i][j]; if(max<dp[i][j]) { max=dp[i][j]; col=j; } path[i][j]=new Point(-1,-1); } } else { for(int j=0;j<V-num;j++) { int maxx=-1,maxxcol=0; for(int m=j+1;m<V;m++) {//找到上一次填表中,(j+1)列到最後一列的最大值maxx而且記錄最大值的列maxxcol(保存最優解) if(maxx<b[index][m]) { maxx=b[index][m]; maxxcol=m; } } dp[i][j]=b[i][j]+maxx; path[i][j]=new Point(index,maxxcol); if(max<dp[i][j]) { max=dp[i][j]; col=j; } } } index=i; num++; } temp=(temp>>1);//編碼進行移位 } //System.out.println(max); if(mmax<max) { mmax=max; ms=index; me=col; p=path;//保存最優路徑 } x++; } System.out.println("最大值:"+mmax); Point t=p[ms][me]; System.out.println((1+ms)+"放"+(1+me)); while(t.x!=-1) { System.out.println((t.x+1)+"放"+(1+t.y)); t=p[t.x][t.y]; } }