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. 阿里云ssh免密登陆突然无效

    [root@node03 ~]# ssh-copy-id node02 root@node02's password: sh: .ssh/authorized_keys: Permission den ...

  2. spring boot 依赖配置

    虽然springboot号称是零配置 配置文件确实不需要,但是 依赖还是要有的 <parent>        <groupId>org.springframework.boo ...

  3. sql存储过程循环实现事务

    //往一张表中添加数据,获取添加数据生成的ID,再往另一张表中添加多条数据 ALTER PROCEDURE [dbo].[AttendanceCardAndDetail_Add] @SchoolID ...

  4. AcWing 224. 计算器 (BSGS算法)打卡

    题目:https://www.acwing.com/problem/content/226/ 题意:有一个计算器能完成三种功能 1.给定Y,Z,P,计算YZModPYZModP 的值: 2.给定Y,Z ...

  5. ZROI week2

    \[ZROI week2\] 除草机 首先考虑最少的拐点肯定是那种螺旋形状的,然后手玩几个数据发现和列数(行数)有关,且每增加1就是上一个状态加2,直接\(O(1)\)公式即可 吐槽:为啥\(n,m\ ...

  6. SQL必知必会——插入数据(十五)

    1.数据插入 INSERT用来将行插入(或添加)到数据库表.插入有几种方式: 插入完整的行插入行的一些部分插入某些查询的结果注意:1.使用INSERT语句可能需要客户端/服务端DBMS中的特定安全权限 ...

  7. (57)C# frame4 调用frame2

    http://msdn.microsoft.com/zh-cn/library/bbx34a2h.aspx https://www.cnblogs.com/weixing/archive/2012/0 ...

  8. SPSS转换菜单:创建时间序列

    SPSS转换菜单:创建时间序列 1.概念:"创建时间序列"对话框允许您基于现有数值型时间序列变量的函数创建新的变量.这些转换后的值在时间序列分析中非常有用. 2.操作:转换-创建时 ...

  9. JavaScript中如何让图形旋转不会相互影响

    最近在联系JavaScript 二维绘图,经常会用到旋转,前几篇博文也提到过这类问题. 但是我忘记了JavaScript二维绘图中有关旋转最核心的两个方法:save()和restore() 在w3c上 ...

  10. Jackson教程

    Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象.Jackson所依赖的jar包较少,简 ...