zoukankan      html  css  js  c++  java
  • P1103 书本整理 题解

    CSDN同步

    原题链接

    简要题意:

    给定 (n) 个二元组 ({x,y}),你的任务首先要将它们按照 (x) 排序(保证 (x) 两两不同),然后从中去掉 (k) 个二元组,使得 剩下的每相邻二元组 (y) 的差的绝对值之和最小,求这个最小值。

    (n leq 100 , x,y leq 200).

    原题中书的高度即为 (x),书的宽度即为 (y).

    首先我们建立结构体 ( ext{book {height , width}}) 来存储每一本书的情况,便于排序操作。其次我们考虑,类似 (n space ext{choose} space k) 的做法,数据范围很弱,考虑用 动态规划 做。

    考虑反其道而行之,去掉 (k) 个也就是反选 (n-k) 个,换成了熟悉的形式。用 (f_{i,j}) 表示前 (i) 本书选 (j) 本(必须选第 (i) 本)的最优答案。

    这样很容易得到:

    [f_{i,l} = egin{cases} 0 space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space space , l = 1 \ min_{j=1}^i f_{j,l-1} + |a_i . ext{width} - a_j . ext{width}| , l > 1\ end{cases}]

    第一行是边界条件,很显然选 (1) 个肯定是 (0). 其余情况枚举从那里开始选就可以了。

    时间复杂度:(mathcal{O}(n^3)).

    实际得分:(100pts).

    // 其实不用开 long long , 特此注明
    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N=1e2+1; 
    
    inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
    
    inline void write(int x) {
    	if(x<0) {putchar('-');write(-x);return;}
    	if(x<10) {putchar(char(x%10+'0'));return;}
    	write(x/10);putchar(char(x%10+'0'));
    }
    
    struct book {
    	int height,width;
    } a[N]; int n,k; 
    ll f[N][N];
    
    inline bool cmp(book x,book y) {
    	return x.height<y.height;
    }
    
    int main() {
    	n=read(),k=read();
    	for(int i=1;i<=n;i++) a[i].height=read(),a[i].width=read();
    	sort(a+1,a+1+n,cmp);
    	memset(f,127,sizeof(f));
    	for(int i=0;i<=n;i++) f[i][1]=0ll; //初始化极大值和边界
    	for(int i=2;i<=n;i++) for(int j=1;j<i;j++)
    	for(int l=2;l<=min(i,n-k);l++)
    		f[i][l]=min(f[i][l],f[j][l-1]+abs(a[i].width-a[j].width)); //转移操作
    	ll ans=(1ll<<62);
    	for(int i=n-k;i<=n;i++) ans=min(ans,f[i][n-k]); //统计答案
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
    
  • 相关阅读:
    微信小程序之文件(图片)使用MD5加密(二)
    微信小程序之文件(图片)使用MD5加密(一)
    02-Django简介
    01-Web框架的原理
    15-pymysql模块的使用
    06-数据类型
    05-表的操作
    04-库的操作
    03-初始mysql语句
    02-MySql安装和基本管理
  • 原文地址:https://www.cnblogs.com/bifanwen/p/13669678.html
Copyright © 2011-2022 走看看