書本整理
阿新 • • 發佈:2022-03-06
今日一題,我以為又是區間dp,結果寫出六重迴圈,又想一想這不是隻列舉一個端點就行嗎。
先看題:
洛谷P1103 書本整理
題目描述
Frank
是一個非常喜愛整潔的人。他有一大堆書和一個書架,想要把書放在書架上。書架可以放下所有的書,所以Frank
首先將書按高度順序排列在書架上。但是Frank
發現,由於很多書的寬度不同,所以書看起來還是非常不整齊。於是他決定從中拿掉k本書,使得書架可以看起來整齊一點。
書架的不整齊度是這樣定義的:每兩本書寬度的差的絕對值的和。例如有4本書:
1×2
5×3
2×4
3×1
那麼Frank
將其排列整齊後是:
1×2
2×4
3×1
5×3
不整齊度就是2+3+2=7
已知每本書的高度都不一樣,請你求出去掉k本書後的最小的不整齊度。
輸入格式
第一行兩個數字n和k,代表書有幾本,從中去掉幾本。(1≤n≤100,1≤k<n)
下面的n行,每行兩個數字表示一本書的高度和寬度,均小於200。
保證高度不重複
輸出格式
一行一個整數,表示書架的最小不整齊度。
輸入輸出樣例
輸入 #1 4 1 1 2 2 4 3 1 5 3 輸出 #1 3首先,可以固定左端點在陣列的最左端,然後從左到右列舉右端點(保證此時的右端點一定不會去掉),再列舉從左端點到右端點中去掉書的本數,這裡就會出現一個問題——右端點前面的那本書(就是右端點前面沒有被刪掉的最接近右端點的那本書)是哪本?為了解決這個問題,就需要再列舉那本書是哪本就可以了。最後如果右端點前沒有書,就記0。
下面是程式碼:
#include<iostream> #include<algorithm> #include<cmath> using namespace std; int n,k; struct node{ int h,w; }a[110]; int f[110][110]; int cmp(node x,node y){ return x.h<y.h; } int main(){ cin>>n>>k; for(int i=1;i<=n;i++){ cin>>a[i].h>>a[i].w; }for(int i=1;i<=n;i++){ f[i][i]=0; } sort(a+1,a+n+1,cmp); a[0].w=a[1].w; for(int i=1;i<=n;i++){ for(int j=0;j<=k&&j<i;j++){ f[i][j]=f[i-1][j]+abs(a[i].w-a[i-1].w); for(int l=1;l<j;l++){ f[i][j]=min(f[i][j],f[i-1-l][j-l]+abs(a[i].w-a[i-1-l].w)); } if(i-1-j==0){ f[i][j]=0; } else{ f[i][j]=min(f[i][j],f[i-1-j][0]+abs(a[i].w-a[i-1-j].w)); } } } int minn=f[n-k+1][1]; for(int i=n-k+2;i<=n;i++){ minn=min(minn,f[i][i+k-n]); } cout<<minn; return 0; }