1. 程式人生 > >P1103 書本整理

P1103 書本整理

fine $1 size 更新 nod mil 求值 高度 pre

題目描述

Frank是一個非常喜愛整潔的人。他有一大堆書和一個書架,想要把書放在書架上。書架可以放下所有的書,所以Frank首先將書按高度順序排列在書架上。但是Frank發現,由於很多書的寬度不同,所以書看起來還是非常不整齊。於是他決定從中拿掉k本書,使得書架可以看起來整齊一點。

書架的不整齊度是這樣定義的:每兩本書寬度的差的絕對值的和。例如有4本書:

1x2 5x3 2x4 3x1 那麽Frank將其排列整齊後是:

1x2 2x4 3x1 5x3 不整齊度就是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

Solution:

  本題換個思維,$n$個去掉$k$個等同於選$n-k$個物品,於是很容易就想到了背包。

  對高度排序後的物品,定義狀態$f[i][j]$表示前$j$個物品中選了$i$個物品的最小值,則初始狀態$f[1][i]=0,i\in[1,n]$(表示從前$i$個裏選$1$個,所求值為$0$)。

  則不難想到狀態轉移方程:$f[i][j]=Min(f[i][j],f[i-1][p]+abs(a[j].w-a[p].w)),i\in[2,n-k],j\in[i,n],p\in[1,j)$,表示前$j$個裏選了$i$個的最小值,由前$p$個中選$i-1$個加上當前搭配的值更新,取值範圍就是一些細節問題不多贅述了。

  那麽最後輸出目標狀態$f[n-k][i],i\in[n-k,n]$中的最小值就$OK$了。

代碼:

 1 #include<bits/stdc++.h>
 2 #define Min(a,b) ((a)>(b)?(b):(a))
 3 #define
For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 4 using namespace std; 5 const int N=205; 6 int n,k,f[N][N],ans=520520520; 7 struct node{ 8 int h,w; 9 bool operator<(const node a)const{return h<a.h;} 10 }a[N]; 11 int main(){ 12 ios::sync_with_stdio(0); 13 memset(f,0x3f,sizeof(f)); 14 cin>>n>>k; 15 For(i,1,n) cin>>a[i].h>>a[i].w; 16 sort(a+1,a+n+1); 17 f[0][0]=0; 18 For(i,1,n)f[1][i]=0; 19 For(i,2,n-k) For(j,i,n) For(p,1,j-1) 20 f[i][j]=Min(f[i][j],f[i-1][p]+abs(a[j].w-a[p].w)); 21 For(i,n-k,n)ans=Min(ans,f[n-k][i]); 22 cout<<ans; 23 return 0; 24 }

P1103 書本整理