其他分享
首页 > 其他分享> > 书本整理

书本整理

作者:互联网

今日一题,我以为又是区间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