卡了好长时间,结果发现是一道普及的题,啪啪啪啪啪。。。。。
虽然dp方程不难想,但是思路还是很重要的,**转化题意**是最重要的一步,例如,抽调k本书,可以转化为在n本书里选择n-k本书,而不是去写sb的3维区间dp,而且根本不可写23333,另外,dp得到的dp[n][n-k]不一定就是答案,要注意到,并不一定最后一本选的书是第n本,所以一定要把dp数组扫一下,再得出最优解!!
dp[i][j]表示在最后一本书为i时,一共选了j本书的最小值。
dp[i][j]=min(dp[i][j],dp[x][j-1])
题目描述
Frank是一个非常喜爱整洁的人。他有一大堆书和一个书架,想要把书放在书架上。书架可以放下所有的书,所以Frank首先将书按高度顺序排列在书架上。但是Frank发现,由于很多书的宽度不同,所以书看起来还是非常不整齐。于是他决定从中拿掉k本书,使得书架可以看起来整齐一点。
书架的不整齐度是这样定义的:每两本书宽度的差的绝对值的和。例如有4本书:
1x2 5x3 2x4 3x1 那么Frank将其排列整齐后是:
1x2 2x4 3x1 5x3 不整齐度就是2+3+2=7
已知每本书的高度都不一样,请你求出去掉k本书后的最小的不整齐度。
附上代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<math.h> using namespace std; struct nod{ int h; int w; }; nod b[105]; int dp[105][105]; inline int cmp(nod a,nod b){ return a.h<b.h; } int main(){ int n,k; cin>>n>>k; for(register int i=1;i<=n;i++){ cin>>b[i].h>>b[i].w; } sort(b+1,b+n+1,cmp); for(register int i=0;i<=n;i++){ for(register int j=0;j<=n;j++){ dp[i][j]=99999999; } dp[i][0]=0; dp[i][1]=0; } for(register int x=2;x<=n-k;x++){ for(register int i=1;i<=n;i++){ if(i<x)continue; for(register int j=i-1;j>=x-1;j--){ dp[i][x]=min(dp[j][x-1]+(int)fabs(b[i].w-b[j].w),dp[i][x]); //cout<<dp[j][x-1]<<‘ ‘<<(int)fabs(b[i].w-b[j].w)<<‘ ‘<<dp[i][x]<<endl; //cout<<i<<‘ ‘<<j<<‘ ‘<<x<<endl<<endl; } } } int ans=99999999; for(int i=n-k;i<=n;i++){ ans=min(ans,dp[i][n-k]); } cout<<ans<<endl; }