• LightOJ1360 Skyscraper(DP)


    题目大概是,一个数轴上n个线段,每个线段都有起始坐标、长度和权值,问从中取出没有公共交点的线段的最大权和。

    取k次是个经典的最小费用最大流问题,不过这题建容量网络有20W个点,离散化最多也要6W个点,跑不动最小费用最大流的样子。。

    其实这题也是个经典的DP,区间图最大权独立集问题,《挑战程序设计竞赛》有介绍。

    • dp[i]表示坐标在[0,i]范围内能得到的最大的线段权值和
    • dp[i]=max(dp[i-1],max(dp[j]+w)([j,i]是一条权w的线段))

    用左闭右开的区间表示这道题的线段。用邻接表存一下各个坐标是哪几条线段的右端点,这样时间复杂度就是O(n+m),n为线段数,m为坐标最大值。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 using namespace std;
     5 struct Edge{
     6     int v,w,next;
     7 }edge[33333];
     8 int NE,head[222222];
     9 void addEdge(int u,int v,int w){
    10     edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
    11     head[u]=NE++;
    12 }
    13 int d[222222];
    14 int main(){
    15     int t,n,a,b,c;
    16     scanf("%d",&t);
    17     for(int cse=1; cse<=t; ++cse){
    18         NE=0;
    19         memset(head,-1,sizeof(head));
    20         scanf("%d",&n);
    21         int mx=0;
    22         while(n--){
    23             scanf("%d%d%d",&a,&b,&c);
    24             addEdge(a+b,a,c);
    25             mx=max(mx,a+b);
    26         }
    27         for(int i=1; i<=mx; ++i){
    28             d[i]=d[i-1];
    29             for(int j=head[i]; j!=-1; j=edge[j].next){
    30                 d[i]=max(d[i],d[edge[j].v]+edge[j].w);
    31             }
    32         }
    33         printf("Case %d: %d
    ",cse,d[mx]);
    34     }
    35     return 0;
    36 }
  • 相关阅读:
    SQL:获取语句执行时间
    好的学习网站和app推荐
    Javascript作业—数组去重(要求:原型链上添加函数)
    Javascript作业—封装type函数,返回较详细的数据类型
    Javascript作业—取字符串的第一个只出现一次的字母
    Javascript作业—数字转化为大写
    HTML入门2—HTML常用标签
    ubuntu 设置静态IP
    centos7 设置 静态IP
    运维常用命令
  • 原文地址:https://www.cnblogs.com/WABoss/p/5247076.html
Copyright © 2020-2023  润新知