假设你想以最美观的方式布置花店的橱窗。如今你有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]; } }