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. PHP closedir() 函数

    打开一个目录,读取它的内容,然后关闭: <?php$dir = "/images/"; // Open a directory, and read its contentsi ...

  2. centos7.5部署ELk

    第1章 环境规划 1.1 ELK介绍       ELK是ElasticSerach.Logstash.Kibana三款产品名称的首字母集合,用于日志的搜集和搜索.      Elasticsearc ...

  3. (转)使用OpenGL显示图像(二)定义Shapes

    定义形状 编写:jdneo - 原文:http://developer.android.com/training/graphics/opengl/shapes.html 在一个OpenGL ES Vi ...

  4. Losing session data in ASP.NET

    Losing session data in ASP.NET By default Response.Redirect terminates thread execution and there mi ...

  5. hbase shell插入根据条件查询数据

    hbase shell插入根据条件查询数据 创建并插入数据: hbase(main):179:0> create 'scores','grade','course' hbase(main):18 ...

  6. 51、tf-idf值提取关键词

    import testWord2vec2 as tw import tensorflow_util as tu import numpy as np model = tw.load_model() n ...

  7. Python变量的下划线

    xx: 公有变量 _x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问 __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部 ...

  8. spark sql数据源--hive

    使用的是idea编辑器 spark sql从hive中读取数据的步骤:1.引入hive的jar包 2.将hive-site.xml放到resource下 3.spark sql声明对hive的支持 案 ...

  9. mybatis之参数处理

    mybatis的mapper接口需要和mapper映射文件进行关联,上一节已经展示接口方法的返回值是如何和mapper映射文件的resultType进行映射.这一节主要讲解接口方法的参数如何与映射文件 ...

  10. 用java api 实现查询 Hive 数据

    版本:cdh5.4.7, hive1.1.0 pom文件 <dependency> <groupId>org.apache.hive</groupId> <a ...