08-12 NOIP模拟测试18

一次考得比一次烂了啊,考试状态也越来越差了啊。。。

又要回到从前吗?。。。

真的是大众分随便拿啊。。。

那我就和大众一起退役吗?。。。

一个T1大模拟明明想到简单的实现方法偏偏要bfs建图,然后建错了吧?呵。

又是一个T1 90,又是细节,A题就那么难???

T1 T2慌的不行,你在想什么啊。。。不,你的大脑已经死机了,你不会想了。。。  可时间不会等你。。。

T2 dp打成shi,觉得暴搜减枝有戏,可你为什么不把它打完却草草了事啊,觉得拿不到100就不要了吗?。。。枝都不减等着TLE吧。

脑子一团浆糊,自己和自己过不去,我就和强迫症卡死一辈子吧。。。

T3 别说了,题都没看,白给的20分不要了。。。

来到第一机房后,真心觉得这里的环境比隔壁好太多,原来那个不敢在大佬们面前出现的我,现在也会主动去问题。

原来静不下心的我,现在一个人单人单桌,思考的更连续更深入了,挺好。

像我这样嘈杂的人,在嘈杂的环境下会死掉吧。。。可我也不要破坏这氛围啊。

所以,我才不要回去。。。

才不要成为

那个别人眼中的"noip大佬",

那个"他们说自己是蒟蒻",

那个什么两个月拿"省二",

那个”暴力最强“。

那个”没那水平还去小机房“。

没关系,我还是说吧。

其实我一直觉得,这是一种瞧不起。。。

是我太敏感了?不过我还是要说

这些字眼让我不爽,似乎一笔一画里都像是在说。。。“这个人没水平,不就是早学了吗?不就是运气好吗?文化课渣成那样,还没状态,我就看不起他”

是,我之前自学过一点,我只会那几个关键字,可我什么算法都没入门。

noip也就提前看了点搜索的概念,考场上靠yy分全是骗来的,我就是当时运气好。

就像xxx说我不行一样,我觉得这些令我无法忍受。

但别人这么做是有理由的,他们的想法是由于我的表现,是我现在太弱了,配不上这个曾经的巧合。

是我之前太放纵自己了,给很多人都留下了不好的印象,给自己太多松懈的空间,抱歉,也是对自己,抱歉。。。

我很讨厌别人看不起我,很害怕别人误解我,我很容易因为别人对我的看法而改变我的行动。

也不能说以别人的意志为转移,但我好像曾经这样,于是我不想继续下去。。。

我不能直接改变别人的想法,但我可以通过改变我的行动而间接影响别人的看法。

于是这是我正在做的,而且,在很大程度上,是为了我,而不是他人。

我想成为真正的有实力的人

我想,这是我的一个进步吧。

87天,来吧。


少有的情绪波动。

我什么时候这么玻璃了?

下午踢球心情好了许多啊。

让这不开心过去吧,只把教训留下。

A. 引子

说下我考场上不动脑子又不想重构的复杂方法。

每次从bfs队列里拿出一个水箱卡住左右边界从上到下扫,扫到一个出发管就找到儿子水箱,建边并放到bfs队列里。

这样能保证前向星扫出来就是深度递减的,对建完的图dfs后根遍历输出答案。

所以实现起来十分复杂,当时明明想到简单方法但是大脑死机了。。。

正解其实就是把那个bfs去掉也不用建图,直接dfs出答案。

不过实现三个方向的移动函数,我觉得还是很帅的。

 1 bool left(int &x,int &y)
 2 {
 3     int ox=x,oy=y;
 4     do{
 5         if(z[x][y-1]=='.') break;
 6         --y;
 7     }while(z[x][y]!='+');
 8     return ox!=x||oy!=y;
 9 }
10 bool right(int &x,int &y)
11 {
12     int ox=x,oy=y;
13     do{
14         if(z[x][y+1]=='.') break;
15         ++y;
16     }while(z[x][y]!='+');
17     return ox!=x||oy!=y;
18 }
19 bool down(int &x,int &y)
20 {
21     do{
22         if(z[x][y]=='-') return true;
23         if(z[x+1][y]=='.') break;
24         ++x;
25     }while(z[x][y]!='+');
26     return false;
27 }

前两个的返回值是 是否移动,down()返回是否遇到水箱顶部。

因为是传引用和题目中左右+下移的组合移动方式。

有以下骚操作:

1 int find(int x,int y,int pre)
2 {
3     if(pre==1) left(x,y);
4     else right(x,y);
5     while(!down(x,y))
6         if(!left(x,y)) right(x,y);
7     return id[x+1][y];
8 }

find()用于实现从一个水箱出发找到儿子水箱,返回找到的水箱的离散编号。

  1 #include<cstdio>
  2 #include<queue>
  3 #include<algorithm>
  4 #define reg register
  5 #define F(i,a,b) for(register int (i)=(a);(i)<=(b);++(i))
  6 using namespace std;
  7 const int N=1025;
  8 const int inf=233333333;
  9 int read();
 10 char z[N][N];
 11 int n,m;
 12 int tx[5]={0,1,0,-1},ty[5]={1,0,-1,0},id[N][N];
 13 struct BK{
 14     int w,a,s,d,id;
 15     BK(){w=a=inf;}
 16 }bk[10086];
 17 int cnt=0;
 18 bool left(int &x,int &y)
 19 {
 20     int ox=x,oy=y;
 21     do{
 22         if(z[x][y-1]=='.') break;
 23         --y;
 24     }while(z[x][y]!='+');
 25     return ox!=x||oy!=y;
 26 }
 27 bool right(int &x,int &y)
 28 {
 29     int ox=x,oy=y;
 30     do{
 31         if(z[x][y+1]=='.') break;
 32         ++y;
 33     }while(z[x][y]!='+');
 34     return ox!=x||oy!=y;
 35 }
 36 bool down(int &x,int &y)
 37 {
 38     do{
 39         if(z[x][y]=='-') return true;
 40         if(z[x+1][y]=='.') break;
 41         ++x;
 42     }while(z[x][y]!='+');
 43     return false;
 44 }
 45 void bfs(int x,int y,int num)
 46 {
 47     queue<pair<int,int> > q;
 48     q.push(make_pair(x,y));
 49     id[x][y]=num;
 50     while(!q.empty())
 51     {
 52         x=q.front().first;
 53         y=q.front().second;
 54         q.pop();
 55         bk[num].w=min(bk[num].w,x-1);
 56         bk[num].s=max(bk[num].s,x+1);
 57         bk[num].a=min(bk[num].a,y-1);
 58         bk[num].d=max(bk[num].d,y+1);
 59         F(i,0,3)
 60         {
 61             int nx,ny;
 62             nx=x+tx[i];
 63             ny=y+ty[i];
 64             if(z[nx][ny]=='-'||z[nx][ny]=='|') continue;
 65             if(id[nx][ny]) continue;
 66             id[nx][ny]=num;
 67             q.push(make_pair(nx,ny));
 68         }
 69     }
 70 }
 71 int find(int x,int y,int pre)
 72 {
 73     if(pre==1) left(x,y);
 74     else right(x,y);
 75     while(!down(x,y))
 76         if(!left(x,y)) right(x,y);
 77     return id[x+1][y];
 78 }
 79 void dfs(int u)
 80 {
 81     for(reg int i=bk[u].s-1;i>=bk[u].w+1;--i)
 82     {
 83         if(z[i][bk[u].a-1]=='-') dfs(find(i,bk[u].a-1,1));
 84         if(z[i][bk[u].d+1]=='-') dfs(find(i,bk[u].d+1,2));
 85     }
 86     printf("%d
",bk[u].id);
 87 }
 88 int main()
 89 {
 90     scanf("%d %d",&n,&m);
 91     F(i,1,n) scanf("%s",z[i]+1);
 92     F(i,0,n+1) z[i][0]=z[i][m+1]='.';
 93     F(i,0,m+1) z[0][i]=z[n+1][i]='.';
 94     F(i,1,n)
 95     {
 96         F(j,1,m)
 97         {
 98             int oj=j,ttx=0;
 99             while(z[i][j]>='0'&&z[i][j]<='9')
100             {
101                 ttx=ttx*10+z[i][j]-48;
102                 ++j;
103             }
104             if(ttx)
105             {
106                 bk[++cnt].id=ttx;
107                 bfs(i,oj,cnt);
108             }
109         }
110     }
111     dfs(1);
112     return 0;
113 }
View Code

B. 可爱精灵宝贝

这题暴搜+减枝玄学复杂度可A。

说正解:区间dp。

设dp[t][i][j][0/1]表示在t时刻[i,j]区间的左或右端点时的最大权值和。

我们把区间离散化,实际让就是用m+1(起点建虚点)个精灵的相对位置作为端点的区间。

然后从小区间转移过来就可以了。

说下这样的正确性:

如果我此时路过一个精灵点,它没消失我肯定是要拿的。

所以区间内的我都有路过,即我能拿的都拿了,不可能再有贡献,也就不需要转移到小区间。

每次能造成贡献的只有区间外的点,Tm^2的复杂度允许,我们可以每次只拿一个点。

即设dp[t][i][j][0/1]从[l+1,r],[l,r-1]转移过来,分类讨论即可。

原文地址:https://www.cnblogs.com/hzoi-yzh/p/11338956.html