zoukankan      html  css  js  c++  java
  • HDU-1051 Wooden Sticks--线性动归(LIS)

    题目大意:有n根木棍(n<5000),每根木棍有一个长度l和重量w(l,w<10000),现在要对这些木头进行加工,加工有以下规则:

        1.你需要1分钟来准备第一根木头。

        2.如果下一根木头比第一根长且重,那么不需准备时间即可加工,否则需要1分钟时间准备。

    木头没有顺序,求最小时间代价。(有多组数据)

    输入:第一行t:需要处理的组数,接下来有t组数据,每组第一行是n,表示木头个数,下一行是n组,每组两个数,表示第i块木头的长、重。

      3 
      5   
      4 9 5 2 2 1 3 5 1 4 
      3 
      2 2 1 1 2 2 
      3 
      1 3 2 2 3 1 

    输出:

      2
      1
      3(注意换行!!!!!!)

    题目分析:一个典型LIS板子题,因为有两个限制条件,所以可以先排序其中一个条件,对另一个条件进行LIS求最少划分数。

          我们可以这么想:现在这些木头已经按长度从小到大排好序了,只要后面一根木头比前面轻,那么代价就+1,所以我们要求最少代价,就是最少划分数,                         划分的依据就是:后一个比前一个木头重,就可以合并,反之则划分数+1。

    以下是代码:

     #include<cstdio>#include<cstring>#include<iostream>

    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    int n;
    
    struct ll{
        int l,w;//定义结构体变量保存长度和重量,便于排序。
    }lw[maxn];
    
    int c[maxn];
    int Max=1; //Max不要设为0,答案最小是1(根据第一条规则) 
    bool cmp(ll a,ll b){
    if(a.l==b.l) return a.w>b.w;
    return a.l<b.l;
    }
    void LIS(){//题目范围是5000,O(n^2)的效率足矣 for(int i=1;i<=n;i++){ c[i]=1; for(int j=1;j<i;j++){ if(lw[i].w<lw[j].w&&c[i]<c[j]+1){//lw[i].w<lw[j].w是lw[i].w>=lw[j].w的反链 c[i]=c[j]+1; Max=max(Max,c[i]); }//最长反链等于最小正链划分数(证明自己百度) //通过求出最长反链的长度即可求得最少代价 } } printf("%d ",Max); } void clear(){ memset(c,1,sizeof(c)); for(int i=1;i<=n;i++){ lw[i].w=lw[i].l=0; } Max=1; }//多组数据的初始化 int main(){ int t; scanf("%d",&t); for(int i=1;i<=t;i++){ scanf("%d",&n); for(int j=1;j<=n;j++){ scanf("%d%d",&lw[j].l,&lw[j].w); } //读入数据 sort(lw+1,lw+n+1,cmp);//对长度进行排序,对重量LIS LIS(); clear(); } return 0; }

    代码就是这样,其中LIS的思想还是很重要的。

  • 相关阅读:
    C++ Sqlite3的基本使用
    DirectX11 初探XMVECOTR&XMMATRIX
    lib和dll文件的初了解
    游戏设计模式——C++单例类
    C++11智能指针的深度理解
    你的文章里为什么不放源码Github链接了
    堡垒机的核心武器:WebSSH录像实现
    Asciinema文章勘误及Web端使用介绍
    Asciinema:你的所有操作都将被录制
    Django实现WebSSH操作物理机或虚拟机
  • 原文地址:https://www.cnblogs.com/liu-yi-tong/p/12650354.html
Copyright © 2011-2022 走看看