T1:

  直接模拟,详见代码注释。

  复杂度$O(NM)$。

Code:

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int N=;
const int M=;
int n,m,tot=;
int a[N][N];
int u[M],d[M],l[M],r[M],bl[M];//上下左右边界及水箱编号
vector<int> v[M],bx[N],by[N];//v做临接表,bx和by存储水箱边界
int get()
{
char c=getchar();
while(c!='.'&&c!='-'&&c!='|'&&c!='+'&&(c<''||c>''))
c=getchar();
if(c>=''&&c<='') return c-'';//水箱编号
else if(c=='-') return -;//横向管道
else if(c=='|') return -;//纵向管道
else if(c=='+') return -;//管道转折,其实和前两个一样,可以不做区分
else return -;//空格子
}
void find(int id,int x,int y)//二分查找水箱边界
{
int xx,yy;
yy=lower_bound(bx[x].begin(),bx[x].end(),y)-bx[x].begin();
r[id]=bx[x][yy];l[id]=bx[x][yy-];
xx=lower_bound(by[y].begin(),by[y].end(),x)-by[y].begin();
d[id]=by[y][xx];u[id]=by[y][xx-];
}
void clean(int id)//将整个水箱的区域都标上该水箱的编号
{
for(int i=u[id];i<=d[id];i++){
for(int j=l[id];j<=r[id];j++)
a[i][j]=id;
}
}
int walk(int x,int y)//沿管道寻找
{
a[x][y]=-;
if(a[x+][y]>) return a[x+][y];//水箱成树形
if(a[x+][y]<=-&&a[x+][y]>=-) return walk(x+,y);
if(a[x][y+]<=-&&a[x][y+]>=-) return walk(x,y+);
if(a[x][y-]<=-&&a[x][y-]>=-) return walk(x,y-);
}
void work(int id)
{
for(int i=d[id];i>=u[id];i--){//水必定先进入靠下的水箱,所以从下到上枚举
if(a[i][l[id]-]<=-&&a[i][l[id]-]>=-)
v[id].push_back(walk(i,l[id]-));
if(a[i][r[id]+]<=-&&a[i][r[id]+]>=-)
v[id].push_back(walk(i,r[id]+));
}
}
void print(int id)//按水箱高度递归输出
{
for(int i=;i<v[id].size();i++)
print(v[id][i]);
printf("%d\n",id);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
a[i][j]=get();//获取格子类型
if(a[i][j]>=&&a[i][j-]>=){//注意水箱编号大于一位的情况
a[i][j]+=*a[i][j-];//用类似快读的思想
a[i][j-]=-;//每个水箱内只能有一个数字
}
if(a[i][j]>=-&&a[i][j]<=-){//将水箱边界存入
bx[i].push_back(j);
by[j].push_back(i);
}
}
}
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(a[i][j]>=){
bl[++tot]=a[i][j];//记录水箱编号,水箱编号可能不连续
find(a[i][j],i,j);//寻找水箱边界
}
}
}
for(int i=;i<=tot;i++) clean(bl[i]);
for(int i=;i<=tot;i++) work(bl[i]);
print();
return ;
}

T1

T2:

  DP好题,不过暴力也能A。

  题目大意:一条线上N个点,共有精灵M个,时间为一时位于K,精灵都有价值,但一段时间后会消失,求收获的最大权值。

  DP(正解):

  

  搜索(暴力):

  

  暴力压正解,我就不说什么了…………

  下面说DP:搜索可以自己想

    设DP数组f[i][j][k],表示i~j已经走过,目前位于i的最大值。

    由于抓取精灵不需要时间,而且权值均为正,所以每次遇到精灵一定会抓。

    先对精灵按照坐标排序。

    将精灵的坐标连同起始点离散,初始化为负无穷,时间为一时起点处权值赋为0。

    这是一个区间DP,先枚举时间,然后枚举区间长度,再枚举左端点,算出右端点。

    然后我们就可以开心地DP了:

      i为时间,L为左端点,R为右端点,val代表精灵的权值,p代表精灵的位置,t为精灵消失的时间。

      f[L-1][R][i+1]=max(f[L-1][R][i+1],f[L][R][i]+val[L-1])  (i+p[L]-p[L-1]<=t[L-1])

      f[L-1][R][i+1]=max(f[L-1][R][i+1],f[L][R][i])      (i+p[L]-p[L-1]>t[L-1])

      f[R+1][L][i+1]=max(f[R+1][L][i+1],f[R][L][i]+val[R+1])  (i+p[R+1]-p[R]<=t[R+1])

      f[R+1][L][i+1]=max(f[R+1][L][i+1],f[R][L][i])      (i+p[R+1]-p[R]>t[R+1])

      f[R+1][L][i+1]=max(f[R+1][L][i+1],f[L][R][i]+val[R+1])  (i+p[R+1]-p[L]<=t[R+1])

      f[R+1][L][i+1]=max(f[R+1][L][i+1],f[L][R][i])      (i+p[R+1]-p[L]>t[R+1])

      f[L-1][R][i+1]=max(f[L-1][R][i+1],f[R][L][i]+val[L-1])  (i+p[R]-p[L-1]<=t[L-1])

      f[L-1][R][i+1]=max(f[L-1][R][i+1],f[R][L][i])      (i+p[R]-p[L-1]>t[L-1])

    后四行的转移方程代表从区间的一头走到另一头再扩展区间,不能丢。

    起点算作一只贡献为0的精灵,方便判断。

    注意判断在该时间内精灵是否已消失。

    DP过程中不断对ans取max,最后的max即为答案。

    共有M只精灵,时间的最大值为T。

    时间复杂度$O(M^2T)$

Code:

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=;
const int M=;
const int inf=;
int n,k,m,t=,ans=;
int s[M],dp[M][M][N];
struct point {
int a,b,c;
}p[M];
bool comp(const point a1,const point a2)
{
return a1.a<a2.a;
}
int main()
{
scanf("%d%d%d",&n,&k,&m);
for(int i=;i<=m;i++){
scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);
t=max(p[i].c,t);
}
p[++m].a=k;
sort(p+,p+m+,comp);
for(int i=;i<=t;i++){
for(int j=;j<=m;j++){
for(int l=;l<=m-j+;l++){
int r=l+j-;
dp[l][r][i]=dp[r][l][i]=-inf;
}
}
}
for(int i=;i<=m;i++){
s[i]=p[i].a;p[i].a=i;
if(s[i]==k)
dp[i][i][]=p[i].b;
}
for(int i=;i<=t;i++){
for(int j=;j<=m;j++){
for(int l=;l<=m-j+;l++){
int r=l+j-;
if(dp[l][r][i]>=){
if(l>=){
int ti=i+s[l]-s[l-];
if(ti<=p[l-].c)
dp[l-][r][ti]=max(dp[l-][r][ti],dp[l][r][i]+p[l-].b);
else
dp[l-][r][ti]=max(dp[l-][r][ti],dp[l][r][i]);
ans=max(ans,dp[l-][r][ti]);
}
if(r<=m-){
int ti=i+s[r+]-s[l];
if(ti<=p[r+].c)
dp[r+][l][ti]=max(dp[r+][l][ti],dp[l][r][i]+p[r+].b);
else
dp[r+][l][ti]=max(dp[r+][l][ti],dp[l][r][i]);
ans=max(ans,dp[r+][l][ti]);
}
}
if(dp[r][l][i]>=){
if(l>=){
int ti=i+s[r]-s[l-];
if(ti<=p[l-].c)
dp[l-][r][ti]=max(dp[l-][r][ti],dp[r][l][i]+p[l-].b);
else
dp[l-][r][ti]=max(dp[l-][r][ti],dp[r][l][i]);
ans=max(ans,dp[l-][r][ti]);
}
if(r<=m-){
int ti=i+s[r+]-s[r];
if(ti<=p[r+].c)
dp[r+][l][ti]=max(dp[r+][l][ti],dp[r][l][i]+p[r+].b);
else
dp[r+][l][ti]=max(dp[r+][l][ti],dp[r][l][i]);
ans=max(ans,dp[r+][l][ti]);
}
}
}
}
}
printf("%d\n",ans);
return ;
}

T2

建议搜索AC的人打一遍DP,毕竟正经NOIP数据是不会这么水的。

NOIP模拟测试18(T3待更新)的更多相关文章

  1. 2019.8.12 NOIP模拟测试18 反思总结

    写个博客总是符合要求的对吧 回来以后第一次悄悄参加考试,昨天全程围观… 然后喜提爆炸120分wwwwwwwww T1用了全机房最慢的写法,导致改掉死循环T掉的一个点以后还是死活过不了最后一个点.T2全 ...

  2. noip模拟测试18

    打开比赛第一眼--超级树? 点开--原题 百感交集-- 欣喜于发现是半年前做过两遍的原题 紧张于如果A不了比较尴尬 绝望于发现根本不会做了 瞟了一眼t1,瞅了一眼t2,嗯--开始搞t3 10分钟打完暴 ...

  3. NOIP模拟测试18「引子·可爱宝贝精灵·相互再归的鹅妈妈」

    待补 引子 题解 大模拟,注意细节 代码1 #include<bits/stdc++.h> using namespace std; int n,m;char a[1005][1005]; ...

  4. NOIP模拟测试17&18

    NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...

  5. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  6. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  7. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

  8. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

  9. 「题解」NOIP模拟测试题解乱写I(29-31)

    NOIP模拟29(B) T1爬山 简单题,赛时找到了$O(1)$查询的规律于是切了. 从倍增LCA那里借鉴了一点东西:先将a.b抬到同一高度,然后再一起往上爬.所用的步数$×2$就是了. 抬升到同一高 ...

随机推荐

  1. 页面重置样式reset.css

    我把经常用到的一些页面重置样式归类到了一个.css文件中,这样可以减少代码冗余.当然还有其他的很多用处,比如h1~h5的样式全部统一的话,下面写东西很清晰很多. @charset 'utf-8'; h ...

  2. ansible_playbook语法中的循环语句归纳

    种类一.标准循环添加多个用户 - name: add several users user: name={{ item }} state=present groups=wheel with_items ...

  3. 【Flutter学习】之绘画实例(一)

    一,概述 画布(Canvas) 画布是一个矩形区域,我们可以控制其每一像素来绘制我们想要的内容 Canvas 拥有多种绘制点.线.路径.矩形.圆形.以及添加图像等的方法,结合这些方法我们可以绘制出千变 ...

  4. eureka学习(一)

    eureka是一个注册中心,与zookeeper不同的是,eureka是restful格式的调用,zk是rpc,还有就是zk保证一致和容错,eureka则是可用和容错. 使用时首先要加入依赖 < ...

  5. BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...

  6. 项目质量管理—七种基本质量工具

    出处:PMBOK(第五版) P236 1.因果图,又称鱼骨图或石川图 用来追溯问题来源,回推到可行动的根本原因.(找根本原因) 2.流程图,也称过程图 用来显示在一个或多个输入转化成一个或多个输出的过 ...

  7. postgreSQL执行计划

    " class="wiz-editor-body wiz-readonly" contenteditable="false"> explain命 ...

  8. Container 技能图谱skill-map

    # Container 技能图谱 ## 1. 容器核心 - [Docker](https://www.docker.com/) - [LXC](https://linuxcontainers.org/ ...

  9. 树莓派2代 B型 4核 1G内存 raspberry pi 2 model B

    树莓派技术交流群:318799602 期盼已久的PI2 已经到货,Element14版,非RS版本.诚信卖家如期发货,不会像某些淘宝卖家一样,没有货还标注现货,发货时间一拖再拖. 树莓派的最新力作!! ...

  10. shell从字符串中提取子串(正则表达式)

    通过试验,可以通过grep.sed两种方式实现. 假设需要提取libgcc-4.8.5-4.h5.x86_64.rpm中的版本号. grep echo "libgcc-4.8.5-4.h5. ...