考试题。

是个DP。

50分可以通过子集枚举+线段覆盖(贪心)完成。

考试没时间写了一个子集枚举30分。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 20;
int read() {
char ch = getchar(); int u = 0, f = 1;
while (!isdigit(ch)) {if (ch == '-')f = -1; ch = getchar();}
while (isdigit(ch)) {u = u * 10 + ch - 48; ch = getchar();}return u * f;
}
//int dp[maxn][maxn]...
struct ioi{
int l, r, num;
double p;
}b[maxn];
bool cmp(ioi a, ioi b)
{
if(a.l == b.l) return a.r < b.r;
return a.l < b.l;
}
int a[maxn], n, q, seq[maxn], last;
double now = 0, ans;
void print_subset(int s, int n)
{
memset(a, 0, sizeof(a));
for(int i = 1; i <= n; i++)
if(s & (1 << (i-1))) a[i] = 1;
}
int main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
n = read(); q = read();
for(int i = 1; i <= n; i++)
{
b[i].l = read(); b[i].r = read(); scanf("%lf",&b[i].p);
//cin>>b[i].l>>b[i].r>>b[i].p;
b[i].r += q; b[i].num = i;
}
sort(b+1, b+1+n, cmp);
for(int i = 1; i < (1 << n); i++)
{
print_subset(i, n);
now = 0; last = 0;
for(int j = 1; j <= n; j++)
{
if(a[j] == 1 && b[last].r <= b[j].l)
{
now += b[j].p;
last = j;
}
}
if(now > ans)
{
for(int j = 1; j <= n; j++)
seq[j] = a[j];
ans = now;
}
}
printf("%0.3lf\n",ans);
for(int i = 1; i <= n; i++)
{
if(seq[i] == 1)
printf("%d ", b[i].num);
}
return 0;
}

注意一点:memset初始化是O(n)的。尽管上次morslin跟我说做试验memset确实比for一遍快...所以我信了他每次枚举memset了一个1e6的数组..TLE

考虑正解的DP。

说过状态设的好,转移就方便。

一开始设的DP[i][j]表示前i个选了j个的最优..

转移个锤子。

正解:不妨设DP[i]表示在第i时,可以获得的最大期望(此期望非彼期望)。

于是只有在第j个结束时间为i才转移,其他的是DP[i] = DP[i-1]

注意a[j].l这个边界,要>q才能转移,会被卡。不写只有50分。

$ if(a[j].r == i && a[j].l >= q) $

$ DP[i] = max(DP[i], DP[a[j].l-q] + a[j].p) $

这时候得到一个O(MN)的DP。M为最大时间

考虑再优化,如果我们先给每个信息排一遍序,这样我们随着时间i的增大,每个a[j].l和a[j].r也在增大。记录上次枚举到的j是多少,记为pos,下次直接从j = pos开始。

我们再去枚举每个j的时候就不需要从1开始了,因为每次满足的先行条件是a[j].r == i。

注意一点,不论这次a[j]有没有更新DP[i]的值,我们的pos都要改变,否则还是TLE。

code:

#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 10;
inline int read() {
char ch = getchar(); int u = 0, f = 1;
while (!isdigit(ch)) {if (ch == '-')f = -1; ch = getchar();}
while (isdigit(ch)) {u = u * 10 + ch - 48; ch = getchar();}return u * f;
}
double dp[maxn];
struct ioi{
int l, r, num;
double p;
}a[maxn];
int n, m, q, pos = 1, pre[maxn], ans[maxn], Ans[maxn], cnt;
bool cmp(ioi a, ioi b)
{
if(a.r != b.r)
return a.r < b.r;
else return a.l < b.l;
}
int main()
{
//freopen("math.in","r",stdin);
//freopen("math.out","w",stdout);
scanf("%d%d",&n,&q);
for(int i = 1; i <= n; i++)
{
scanf("%d%d%lf",&a[i].l,&a[i].r,&a[i].p);
a[i].num = i;
m = max(m, a[i].r);
}
sort(a+1, a+1+n, cmp); for(int i = 1; i <= m; i++)
{
dp[i] = dp[i-1]; pre[i] = i - 1;
for(int j = pos; j <= n; j++)
{
if(a[j].r > i) break;
if(a[j].r == i)
{
if(a[j].l >= q && dp[i] < dp[a[j].l-q] + a[j].p)
{
dp[i] = dp[a[j].l-q] + a[j].p;
ans[i] = a[j].num;
pre[i] = a[j].l - q;
}
if(a[j].num == 1 && dp[i] < dp[a[j].l-q] + a[j].p)
{
dp[i] = dp[a[j].l-q] + a[j].p;
ans[i] = a[j].num;
pre[i] = 0;
}
pos = j;
}
}
}
int now = m;
while(now)
{
if(ans[now]) Ans[++cnt] = ans[now];
now = pre[now];
}
printf("%0.3lf\n",dp[m]);
for(int i = cnt; i >= 1; i--)
printf("%d ",Ans[i]);
return 0;
}

输出路径的时候是while(now),不是while(pre[now])..

我说怎么输出不了最后一个..

【noip模拟赛 王强的疑惑】 题解的更多相关文章

  1. NOIP模拟赛 打铁的匠 题解

    [问题描述] Mark Douglas是一名优秀的锻造师.与他优秀的锻造水平不相符,他非常穷,以至于很多好刀都因为缺少素材缺少资金无法打造. Mark把他有能力锻造的所有n种刀建成了一棵锻造树,除了第 ...

  2. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  3. CH Round #49 - Streaming #4 (NOIP模拟赛Day2)

    A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...

  4. CH Round #48 - Streaming #3 (NOIP模拟赛Day1)

    A.数三角形 题目:http://www.contesthunter.org/contest/CH%20Round%20%2348%20-%20Streaming%20%233%20(NOIP模拟赛D ...

  5. CH Round #54 - Streaming #5 (NOIP模拟赛Day1)

    A.珠 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2354%20-%20Streaming%20%235%20(NOIP模拟赛Day1)/珠 题解:sb题, ...

  6. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  7. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  8. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  9. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

随机推荐

  1. POJ 1789(最小生成树)

    这题要把给的字符串变成边的权值 #include <cstdio> #include <iostream> #include <queue> #include &l ...

  2. csharp:A Custom CheckedListBox with Datasource

    /// <summary> /// (eraghi) /// Custom CheckedListBox with binding facilities (Value property) ...

  3. Linux 添加yum命令

    第一步,国内的yum仓库 http://mirrors.163.com/centos/7/os/x86_64/Packages/ http://mirrors.aliyun.com/centos/7/ ...

  4. javascript实现数据结构: 树和森林

    树的3种常用链表结构 1 双亲表示法(顺序存储结构) 优点:parent(tree, x)操作可以在常量时间内实现 缺点:求结点的孩子时需要遍历整个结构 用一组连续的存储空间来存储树的结点,同时在每个 ...

  5. Git 拉取Gitee仓库报错:“fatal: unable to access ''": Failed to connect to 127.0.0.1 port 1080: Connection refused”

    1.报错信息: 2.本地查看是否Git使用了代理 git config --global http.proxy 3.取消代理 git config --global --unset http.prox ...

  6. Java 快速入门-06-JDK 目录文件说明

    Java 快速入门-06-JDK 目录文件说明 JDK:开发环境,搞技术的人或者应用服务器使用 JRE:运行环境,如浏览器插件或者Swing界面的客户端等最终用户需要使用 JDK自含一个JRE,并依赖 ...

  7. CentOS随笔 - 2.CentOS7安装ftp支持(vsftpd)

    前言 转帖请注明出处: http://www.cnblogs.com/Troy-Lv5/ 在前一篇文章中介绍了在虚拟机中安装CentOS7, 接下来就要进行配置了, 第一个就是安装ftp支持. 要不然 ...

  8. css网页中设置背景图片的方法详解

    在css代码中设置背景图片的方法,包括背景图片.背景重复.背景固定.背景定位等   用css设置网页中的背景图片,主要有如下几个属性: 1,背景颜色 {">说明:参数取值和颜色属性一样 ...

  9. kettle使用命令行传入数据库链接参数(ip、数据库、端口、用户、密码)执行job时子转换失败。

    使用cmd 传参数执行 kettle job 遇到错误: 错误原因,无法找到文件.... 原来使用,通过目录指定转换,好处是:当以文件资源库保存时,可以直接将文件夹复制走,直接运行就可以,不需要单独针 ...

  10. Python初学者第十九天 函数(3)

    19day 函数 1.作用域 Python中,一个函数就是一个作用域.所有的局部变量都是放在当前的作用域里面 代码定义完成后,作用域已经生成,作用域链向上查找 2.匿名函数 当需要暂时性的用到一个函数 ...