花店櫥窗佈置問題(FLOWER)

問題描述

  假設你想以最美觀的方式佈置花店的櫥窗。如今你有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

Java代碼實現

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];
		}
	}

運行結果

今天老師上完課說全部花都要被放,這個算法仍是考慮多了,包含了這個選擇,代碼就不給了,用dp思想就能夠解決了。

相關文章
相關標籤/搜索