书本整理
作者:互联网
今日一题,我以为又是区间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; }
标签:书架,int,Frank,整齐,枚举,端点,整理,书本 来源: https://www.cnblogs.com/z-2-we/p/15971229.html