《算法導論》思考題15-2 整齊打印

     畫外音:沒想作到15-2題也是費了一番周折,看來《算法導論》裏題都不是白給的ios

 

  整齊打印問題: 考慮在一個打印機上整齊地打印一段文章的問題。輸入的正文是n個長度分別爲L一、L二、……、Ln(以字符個數度量)的單詞構成的序列。咱們但願將這個段落在一些行上整齊地打印出來,每行至多M個字符。「整齊度」的標準以下:若是某一行包含從i到j的單詞(i<j),且單詞之間只留一個空格,則在行末多餘的空格字符個數爲 M - (j-i) - (Li+ …… + Lj),它必須是非負值才能讓該行容納這些單詞。咱們但願全部行(除最後一行)的行末多餘空格字符個數的立方和最小。請給出一個動態規劃的算法,來在打印機整齊地打印一段又n個單詞的文章。分析所給算法的執行時間和空間需求。git


 

  在網上很是認真地看了幾篇關於這個整齊打印的博客,發現真的都是錯誤的!很是坑人!傳送門我就不開了,雖然說對思路會一些啓發可是少一個準確的版原本解決這個問題。算法

這個問題的核心思想依然是動態規劃,而動態規劃的關鍵在於找到整個解決過程的最優子結構。數組

  咱們聲明一個數組來儲存隨着單詞長度增長的動態最優解op[](在下面的代碼中爲了實現隨機長度解決該問題使用了vector動態分配),在動態規劃的過程之中的第n級最優子結構咱們須要計算的是 1)第n-1到1級的最優化解  2)連續串接的 i 到 j 個單詞在limit長度限制下的代價(weight)。app

  公式表達爲  op[n]=min{op[k-1]+cost(k,n)...} ////k爲循環遍歷的值 k從n到 1,整個計算過程爲狀態轉移的過程測試

/*當 k==n的時候,表示前面n-1個單詞構成的最優化結構不須要對齊,直接以新的一行添加入 */優化

  爲了儘可能減小算法的時間複雜度,咱們可使k從n向小遍歷,這樣以來能夠檢測當前 從k到n個單詞所須要的代價大於一行的限制的時候跳出循環。spa

屢次運行測試沒有發現問題,歡迎幫我找一些BUGblog

#include<string>
#include<iostream>
#include<vector>
#include<cstdlib>

#define MAX_VAL 999999

using namespace std;

int g_iLast=0;
int g_iLimit=MAX_VAL;
int g_iLen=0;
vector<int> g_vecOp;  ////optimal amount for weight
vector<string> g_vecWord; ////////Storing the words
vector<int> g_vecIndex;

int space(int index){
	////////// index>=1
	int total=g_iLimit;
	for(int i=1;i<=g_iLen;i++){
		if(g_vecIndex[i]==index){
			total-=g_vecWord[i-1].size();
			total--;
		}
	}
	return total;////// A bug!
}

int space(int i,int j){
	/////// 1<=i<=j<=len
	int total=0;
	for(int x=i;x<=j;x++){
		total+=g_vecWord[x-1].size();
	}
	return g_iLimit-j+i-total;
}


void optimal(){
	int iCur=1;
	for(int i=1;i<=g_iLen;i++){
		////// Descend Order to Save More Time
		g_vecOp[i]=MAX_VAL;
		int iSpace=space(iCur);
		int iSize=g_vecWord[i-1].size();
		if(iSpace>=iSize){
			//////// The Space Enough to append
			g_vecIndex[i]=iCur;
			g_vecOp[i]=g_iLast+(iSpace-iSize)*(iSpace-iSize)*(iSpace-iSize);

		}else{
			/////// If Not
			iCur++;
			g_iLast=g_vecOp[i-1];
			int min=MAX_VAL;
			for(int j=i;j>1;j--){
				int s=space(j,i);
				if(s<0)break;
				int temp=g_vecOp[j-1]+s*s*s;
				if(min>temp){
					min=temp;
					for(int m=j;m<=i;m++){
						g_vecIndex[m]=iCur;
					}
				}
			}g_vecOp[i]=min;
			g_vecIndex[i]=iCur;
		}
	}
	cout<<"The cubic minimum of blank is "<<g_vecOp[g_iLen]<<endl<<endl;
}







int main(){
	cout<<"Input the total amount of your Word: "<<ends;
	cin>>g_iLen;
	///////////////////////
	string szTmp;
	for(int i=0;i<g_iLen;i++){
		cin>>szTmp;
		g_vecWord.push_back(szTmp);
	}
	///////////////////////
	cout<<"Input your maximun digits of letters allowed in a line :"<<ends;
	cin>>g_iLimit;
	for(int i=0;i<=g_iLen;i++){
		g_vecOp.push_back(0);
		g_vecIndex.push_back(0);
	}
	/////////////////////// Initializing Complete

	optimal();
	//////////////////////Outputting
	int now=1;
	for(int i=1;i<=g_iLen;i++){
		if(g_vecIndex[i]>now){
			now++;
			cout<<endl<<g_vecWord[i-1]<<' '<<ends;
		}else{
			cout<<g_vecWord[i-1]<<' '<<ends;
		}
	}
	return 0;
}
相關文章
相關標籤/搜索