CERC 2014 Outer space invaders (hnuoj13405)

这里写的是区间dp做法,先将时间进行离散化处理
打高敌人时可以顺便干掉较矮的敌人,故每次考虑区间最高敌人
dp[i][j]表示消灭出现时间大于x小于j这一段敌人的最小花费
则dp[i][j]=dp[i][k]+dp[k][j]+mh.其中mh是i,j段出现的最高敌人的高度,k为区间内所有最高敌人可能出现的点
看见网上其他大神都拿着stl离散化各种处理,这里贴一个没什么STL的版本

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=308;
const int INF=0x7f7f7f7f;
struct fuck{
    int x,y,h;
}f[maxn];
int n;
int a[maxn<<2];
int b[maxn<<2];
int dp[maxn<<2][maxn<<2];
int scan()
{
    int res = 0, ch, flag = 0;  

    if((ch = getchar()) == ‘-‘)             //判断正负
        flag = 1;  

    else if(ch >= ‘0‘ && ch <= ‘9‘)           //得到完整的数
        res = ch - ‘0‘;
    while((ch = getchar()) >= ‘0‘ && ch <= ‘9‘ )
        res = res * 10 + ch - ‘0‘;  

    return flag ? -res : res;
}
int lb(int x,int l,int r)
{
    int mid;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(b[mid]<x)
            l=mid+1;
        if(b[mid]==x)
            return mid;
        if(b[mid]>x)
            r=mid-1;
     }
}
int main()
{
    int i,j,t,k;
    scanf("%d",&t);
    int pp[maxn];
    while(t--)
    {
        scanf("%d",&n);
        int idx=0,id=0;
        for(i=1;i<=n;i++)
        {
            f[i].x=scan();f[i].y=scan();f[i].h=scan();
            a[idx++]=f[i].x;a[idx++]=f[i].y;
        }
        sort(a,a+idx);
        b[++id]=a[0];
        for(i=1;i<idx;i++)
            if(a[i]!=a[i-1])
                b[++id]=a[i];
        for(i=1;i<=n;i++)
        {
            f[i].x=lb(f[i].x,1,id);
            f[i].y=lb(f[i].y,1,id);
        }
        int len=id+1;
        for(i=0;i<=len;i++)
            dp[i][i]=0;
        for(int d=1;d<=len;d++)
            for(i=0;i+d<=len;i++)
            {
                int j=i+d;
                int mh=-1,idh=0;
                for(k=1;k<=n;k++)
                    if(f[k].x>i&&f[k].y<j)
                    {
                        if(f[k].h>=mh)
                        {
                            if(f[k].h>mh)
                            {
                                idh=0;
                                pp[++idh]=k;
                                mh=f[k].h;
                            }
                            else
                                pp[++idh]=k;
                        }
                    }
                if(mh==-1)    dp[i][j]=0;
                else
                {
                    dp[i][j]=INF;
                    while(idh>0)
                    {
                        int xx=pp[idh--];
                        for(k=f[xx].x;k<=f[xx].y;k++)
                            if(dp[i][j]>dp[i][k]+dp[k][j]+mh)
                                dp[i][j]=dp[i][k]+dp[k][j]+mh;
                    }
                }
            }
        printf("%d\n",dp[0][len]);
    }
    return 0;
}
时间: 2024-10-18 20:03:38

CERC 2014 Outer space invaders (hnuoj13405)的相关文章

bzoj 3928: [Cerc2014] Outer space invaders

$f[i][j]$表示消灭起始时间在$(i,j)$内的外星人所花费的最小代价. 考虑在这个区间内距离最远的外星人h,在他的区间中一定要选一个点要开一炮,而且这一炮可以顺便把其他跨过这个点的敌人消灭,剩下只需消灭没有跨过这个点的敌人. 枚举开炮时间$f[i][j]=min(f[i][k]+f[k][j]+d[h])$. 区间需要离散化. #include<iostream> #include<cstdio> #include<cstring> #include<al

BZOJ3928 [Cerc2014] Outer space invaders

第一眼,我勒个去...然后看到n ≤ 300的时候就2333了 首先把时间离散化,则对于一个时间的区间,可以知道中间最大的那个一定要被选出来,然后把区间分成左右两份 于是区间DP就好了,注意用左开右开的区间比较方便2333 如果暴力找区间内最大值是O(n3)的,当然st表就是O(n2logn)的了...不过st表辣么难蒟蒻根本不会QAQQQ 1 /************************************************************** 2 Problem: 3

Wheels(bfs遍历,CERC 2014)

原题链接:http://acm.hnu.cn/online/?action=problem&type=show&id=13397 对于每一个已经开始运动的轮子要求它周围和他相接触的轮子的运动状态,然后让那些轮子依次进入队列= = 速度关系== 高中学过物理应该都知道吧 1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #inc

Space Invaders 太空侵略者

发售年份 1978 平台 街机 开发商 Taito 类型 射击 https://www.youtube.com/watch?v=MU4psw3ccUI 原文地址:https://www.cnblogs.com/revoid/p/10340004.html

OC中使用字典管理颜?

处理?程?件crayons.txt中的?本信息,?本内容是关于颜色的,每?都是?个颜?的信息,例如:Almond #EED9C4,前?个字符串是颜?色的名称,后?个字符串是颜色的16进制?值,处理?本完成如下需求: 1.使用字典管理所有的颜?,即字典中存储的是多个键值对,颜?名称为key,16进制颜?色值(不带#)是value. 2.取出所有的key,升序排列. 3.取出所有的value,按照排序后的key排列. 4.使?用?个新的字典管理颜色,对颜?进?分类管理,即:“A”,“B”,“C”..

Linux实验一

一.Linux 简介 实验介绍 本节主要介绍 Linux 的历史,Linux 与 Windows 的区别等入门知识.如果你已经有过充分的了解,可以跳过本节,直接进入下一个实验. 一.Linux 为何物 Linux 就是一个操作系统,就像你多少已经了解的 Windows(xp,7,8)和 Max OS ,至于操作系统是什么,就不用过多解释了,如果你学习过前面的入门课程,应该会有个基本概念了,这里简单介绍下操作系统在整个计算机系统中的角色. 我们的 Linux 也就是系统调用和内核那两层,当然直观的

第一次实验报告

实     验    报     告 课程:信息安全系统设计基础  班级:1353 姓名:黎静  学号:20135338 成绩:             指导教师:娄嘉鹏    实验日期:2015.9.20 实验密级:         预习程度:         实验时间:10:00--22:00 仪器组次:29         必修/选修: 选修            实验序号:1~12 第一次实验部分截图 一.Linux 简介 实验介绍 本节主要介绍 Linux 的历史,Linux 与 Wi

托福分类词汇

托福分类词汇表(共17类863个常用单词) 一.   psychology 心理 1.       mental 心理的 2.       physical 身体的,物质的,物理的 3.       spiritual 心灵的 4.       conformity 从众 5.       majority 多数人 6.       minority 少数人 7.       threshold judgment (心理学)初始性判断 8.       subject 受实验对象 9.     

经典把妹桥段:Flower dance开头对话

听到一首很赞的钢琴曲,Flower Dance,其开头有一段英文对话,如下: Lucy:"They serve the purpose of changing hydrogen into breathable oxygen, and they’re as necessary here as the air is, on Earth." Lucy:“它们把水转化为可供呼吸的氧气,它们像地球上的空气一样重要呢.” Ray:"But I still say……they’re flo