打完比赛才知道,我学过搜索吗?


USACO2013 黑洞

问题描述:
李宗泽的爱好是在周末进行物理学实验,但事与愿违,实验将N个黑洞(2 <= N <= 12, N为even)具象化在了他的农场里,每个都有明确的坐标位置。
根据他的计算,李宗泽知道将会形成N/2对连接起来的黑洞。如果黑洞A和B被连成一对,那么任何物体进入黑洞A,将会以进入黑洞A的方向从黑洞B中出来;进入黑洞B,也会以进入时的方向从黑洞A中出来。举例来说,黑洞A在(0,0),黑洞B在(1,0),牛玉鑫从(1/2,0)开始向X轴正方向移动,进入黑洞B,从黑洞A中出来,将继续向X轴正方向移动,再次进入黑洞B,被困在一个循环里。
李宗泽知道每一个黑洞在他的农场上的具体坐标,牛玉鑫只会向X轴正方向移动,但却不知道牛玉鑫目前的位置。
请你帮助李宗泽计算共有多少种黑洞配对方法会使在不幸的位置的牛玉鑫陷入循环。

输入说明:
第一行:一个正整数N;
第二到N+1行:每行两个整数X,Y描述一个黑洞的位置,每个坐标在0..1,000,000,000内。

样例输入:(wormhole.in)
4
0 0
1 0
1 1
0 1
有4个黑洞,形成一个正方形的循环。

输出说明:
第一行:一个数,代表所有的会让牛玉鑫陷入循环的黑洞配对方法数。

样例输出:(file wormhole.out)
2
给这4个黑洞编号为1..4。如果将1和2相连,3和4相连,牛玉鑫从1和2之间或3和4之间出发时会陷入循环。相同的,如果连接1和3,2和4,牛玉鑫也会陷入循环。只有连接1和4,2和3,牛玉鑫从任何一个位置开始移动都不会陷入循环。

数据那么小,暴力嘛。算了一下,n=12的时候最多也只是11*9*7*5*3*1=没多少种 配对方式,枚举无障碍。但是一开始思路被图论拘住了,只想着连边判环,对水平线上右边的黑洞单向建边,配对黑洞之间双向建边,从第一个点开始扫一遍。对于一个点,优先走配对黑洞,如果没有就走右边的单向边居然也骗了50分。

仔细想这种思路是错误的。因为显然每个黑洞都是有配对黑洞的,我那个sb理论根本不成立,只能水个样例,和真实情况完全不一样。它应该是从不同的点开始搜判环,但是我没重敲这个思路,有机会试试。

为什么不敲呢,因为我看见官方绝妙的题解。这个判环真的好巧妙啊,好优雅啊………………
唯一值得欣喜的是,我的配对枚举写得还是很好看的。

#include<bits/stdc++.h>
using namespace std;int n;
struct farm_
{int x,y;
}a[20];
int next_[20],partner_[20];//next_[i]=i点右边相邻的那个点,partner_[i]=与i匹配的黑洞。
bool flag[20];//是否配对。
int ans=0;inline void read(int &x)
{x=0;int f=1;char s=getchar();for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;for(;s>='0'&&s<='9';s=getchar()) x=(x<<3)+(x<<1)+s-48;x*=f;}bool check()//判断是否有环。
{for(int i=1;i<=n;++i){int x=i;for(int j=1;j<=n;++j) x=next_[partner_[x]];//太强了这里,即从i点开始,不断地重复传送黑洞-右行-传送的过程,正常情况下最多n遍,n个点嘛。if(x) return true;//如果出现某一次,n遍之后右边仍然有点,说明死循环了。}return false;
}void dfs(int x)
{if(x==n) {if(check()) ++ans;return;}//配完啦。int xx;for(int i=1;i<=n;++i)if(!flag[i]){xx=i;break;}//找到第一个没配对的点,这样就可以有效避免重复遗漏,这是我正常测试唯一带脑子的地方了。flag[xx]=1;for(int i=xx+1;i<=n;++i)if(!flag[i]){flag[i]=1;partner_[xx]=i;partner_[i]=xx;dfs(x+2);partner_[xx]=0;partner_[i]=0;flag[i]=0;//回个溯。}flag[xx]=0;return;
}void init()
{read(n);for(int i=1;i<=n;++i)  read(a[i].x),read(a[i].y);
}void work()
{memset(next_,0,sizeof(next_));memset(partner_,0,sizeof(partner_));for(int i=1;i<=n;++i)for(int j=1;j<=n;++j) if(a[i].y==a[j].y&&a[i].x<a[j].x&&(a[next_[i]].x-a[i].x>a[j].x-a[i].x||!next_[i]))next_[i]=j;//找啊找啊找右手。memset(flag,0,sizeof(flag));dfs(0);printf("%d",ans);
}int main()
{init();work();return 0;
}

gohome 安全回家

【问题描述】
Farmer John在森林里迷路了,现在他急需要回家。
森林被分成了N*M的矩阵,每个单元格有一个字符来标示属性,’.’表示空地,’V’表示Fj所在的位置,’J’表示Fj家的位置。在森林里有很多危险的地方,危险的地方被标记为’+’。
Fj想要在回家的路上,让自己距离危险的地方尽可能的远,请你帮他设计一条线路,让这条线路上的每个点距离 危险的地方 最近的距离 最大。
假设Fj的位置为 (R,C),某个危险点的位置为 (A,B)Fj距离危险点的距离为:
|R-A| + |C-B|
当然,Fj必须要回家,也许他必须要经过危险的地方。
【输入】
第一行两个整数:N和M (1 ≤ N, M ≤ 500)
接下来N行,每行M个字符,范围是:’.’, ‘+’, ‘V’, ‘J’.
数据保证肯定有’V’, ‘J’,且至少有一个’+’
【输出】
一个整数,表示那个距离

【输入输出样例1】
gohome.in gohome.out
4 4 3
+…
….
….
V..J

【输入输出样例2】
gohome.in gohome.out
4 5 0
…..
.+++.
.+.+.
V+.J+

【数据范围】
30% 数据保证 10,<=N,M<=50

说实话,题目说的那个距离最初惊到我了,我根本不知道它在说什么距离。……幸好我们有万能(假的)的样例。经过手动推演发现题目所求应该是,最小值最大的那条路径上的那个最小值。

好绕。

没关系,可以显然看出,我们要预处理出每个点距离危险位置的最小值,bfs最短路即可,完全没有问题。
至于怎么求解,我是太不熟练了。这种题目的描述应该一眼二分答案。但我考场上写了dfs,T到飞起,让人难过。二分答案的思路很好懂,每次验证一下即可,为了卒我遗志,我还是改了个bfs+bfs的。
要带回溯,长得不伦不类。

#include<bits/stdc++.h>
using namespace std;int n,m;
int a[600][600];
int sx,sy,tx,ty;
struct que
{int x,y;
}q[5000010];
int head,tail;
int s[600][600];
bool flag[600][600];
int ans[600][600]={};//走到这个点时我们最小值中的最大值。
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};inline void read(int &x)
{x=0;int f=1;char s=getchar();for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;for(;s>='0'&&s<='9';s=getchar()) x=(x<<3)+(x<<1)+s-48;x*=f;}void first_()
{memset(a,1,sizeof(a));memset(s,0,sizeof(s));memset(ans,0,sizeof(ans)); head=tail=0;
}void bfs()//预处理,没什么好说的。
{while(head++<tail){int u=q[head].x,v=q[head].y;for(int i=0;i<4;++i){int x=u+dx[i],y=v+dy[i];if(!a[x][y]&&!flag[x][y]){flag[x][y]=1;s[x][y]=s[u][v]+1;q[++tail].x=x;q[tail].y=y;}}}
}void bfs2()
{head=0;tail=0;q[++tail].x=sx;q[tail].y=sy;flag[sx][sy]=1;ans[sx][sy]=s[sx][sy];//起点初始化。while(head++<tail){int u=q[head].x,v=q[head].y;for(int i=0;i<4;++i){int x=u+dx[i],y=v+dy[i];if(a[x][y]!=0) continue;//越界,打入冷宫。if(ans[x][y]<s[x][y]&&ans[x][y]<ans[u][v])////感谢cs的代码支持,我觉得这里的判定也很风骚。ans[x][y]<s[x][y]和ans[x][y]<ans[u][v]都意味着这个点可以更新为更大的。{ans[x][y]=min(s[x][y],ans[u][v]);//取最小值。它要放在外面,因为纵使这个点已经在队中了,它也可以被更新的。if(!flag[x][y]){flag[x][y]=1;q[++tail].x=x;q[tail].y=y;}}}flag[u][v]=0;//回溯。因为它没有人知道如果下次从别的方向走他会不会更小。}
}void init()
{memset(flag,0,sizeof(flag));read(n);read(m);first_();char x;for(int i=1;i<=n;++i)for(int j=1;j<=m+1;++j){scanf("%c",&x);if(x=='.') a[i][j]=0;if(x=='V') a[i][j]=0,sx=i,sy=j;if(x=='J') a[i][j]=0,tx=i,ty=j;if(x=='+') {q[++tail].x=i;q[tail].y=j;flag[i][j]=1;//所有危险位置作为起点进队。}}}void work()
{bfs();  //预处理。memset(a,0,sizeof(a));for(int i=1;i<=n;++i) a[i][0]=a[i][m+1]=16843009;for(int i=1;i<=m;++i) a[0][i]=a[n+1][i]=16843009;//我风骚而造作的边界处理,让它不越界而已,写这么繁琐是个人恶趣味。memset(flag,0,sizeof(flag)); bfs2(); printf("%d",ans[tx][ty]);
}int main()
{init();work();return 0;
}

我的数组越开越混乱了,q的大小也没有把握,交的时候居然开了5w。嗳,反思吧。


meteor 流星雨

【问题描述】
流星雨是美丽的,但是流星落下来也能砸死人的。
有一大片流星要在海亮教育园的操场落下,而小x恰好在操场数星星。小x面临最大的问题不是浪漫,而是保住小命。
我们把海亮教育园的操场认为是坐标系的第一象限。小x现在位于坐标系的原点。
现在有M颗流星会落在海亮教育园的操场上,其中第i颗流星会在时刻T_i砸在坐标为(X_i, Y_i)的格子里。流星的力量会将它所在的格子,以及周围4个相邻的格子都化为焦土,当然小x也无法再在这些格子上行走,这样他会被烧伤。
小x从0时刻开始逃离,他只能上下左右移动,并且一个时刻只能移动一个格子,当然,这个格子必须是完好的。
现在小x想知道,最少经过多少时刻,他可以到达一个安全的格子。
【输入】
一个正整数M
接下来M行,每行3个整数Xi,Yi和Ti。分别表示第i颗流星落下的坐标和时间。保证所有坐标都在第一象限。
【输出】
一个整数,表示最少逃离时刻。如果逃离不了,那么输出-1,表示小x肯定被流星砸着了。

【输入输出样例1】
meteor.in meteor.out
4 5
0 0 2
2 1 2
1 1 2
0 3 5
【样例说明】
一共有4颗流星将坠落在操场,它们落地点的坐标分别是(0, 0),(2, 1),
(1, 1)以及(0, 3),时刻分别为2,2,2,5。

在t=5时的牧场,离小x最近的安全的格子是(3,0)——不过由于早在第二颗流星落地时,小x直接跑去(3,0)的路线就被封死了。离小x第二近的安全格子为(4,0),但它的情况也跟(3,0)一样。再接下来的格子就是在(0,5)-(5,0)这条直线上。在这些格子中,(0,5),(1,4)以及(2,3)都能在5个单位时间内到达。
【数据范围】
20% M<=25
40% M<=200
100% M<=50000 0 <= X_i <= 300;0 <= Y_i <= 300 0 <= T_i <= 1,000

这才是真的一眼题。初始化染个色,裸的bfs就可以。
然而我写炸了。代码里讲。

#include<bits/stdc++.h>
using namespace std;int m;
int a[320][320];
bool flag[320][320];
struct que
{int x,y;int t; //走到这个点的时间。
}q[100000];
int ans=0;
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};inline void read(int &x)
{x=0;int f=1;char s=getchar();for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;for(;s>='0'&&s<='9';s=getchar()) x=(x<<3)+(x<<1)+s-48;x*=f;}void bfs()
{int head=0,tail=0;q[++tail].x=0;q[tail].y=0;q[tail].t=0;while(head++<tail){int u=q[head].x,v=q[head].y;for(int i=0;i<4;++i){int x=u+dx[i],y=v+dy[i];if(x<0||y<0) continue;if(a[x][y]==16843009) {printf("%d",q[head].t+1);exit(0);}//一旦访问到一个安全区域就输出。+1是因为q[head].t是走到head那个点的,要走到这个安全位置还要1个时间单位。if(!flag[x][y]&&a[x][y]>q[head].t+1){flag[x][y]=1;q[++tail].x=x;q[tail].y=y;q[tail].t=q[head].t+1;}//我挂掉的原因愚蠢得可笑,我带了个计数器tott,每次扩展点就++,全然忘记同一层是同一时间,大约也是真没带脑子。样例果然不可信。}}printf("-1");exit(0);
} void init()
{memset(a,1,sizeof(a));read(m);int x,y,z;for(int i=1;i<=m;++i){read(x);read(y);read(z);a[x][y]=min(a[x][y],z);a[x+1][y]=min(a[x+1][y],z);if(x) a[x-1][y]=min(a[x-1][y],z);a[x][y+1]=min(a[x][y+1],z);if(y) a[x][y-1]=min(a[x][y-1],z);//初始化(x,y)最早成为禁区的时间。}
}void work()
{memset(flag,0,sizeof(flag));flag[0][0]=1;bfs();
} int main()
{init();work();return 0;
}

T2T3其实都好做,T1我觉得官方题解那种不太好想。但是最后我差不多也就T1有分,该拿的拿不到,近期是不是太浮躁了一点?据说搜索要告一段落开启dp新征程了,但是什么启发式迭代加深几乎都没有敲过题,well,别颓了。

搜索专练测试 3.2相关推荐

  1. [SOCI2005]最大子矩阵(DP) + [JXOI2018]守卫(DP) + [CQOI2016]手机号码(数位DP)[各种DP专练]

    DP专练博客 DP专练 T1:最大子矩阵 题目 题解 代码实现 T2:守卫 题目 题解 代码实现 T3:手机号码 题目 题解 代码实现 T1:最大子矩阵 题目 这里有一个n*m的矩阵,请你选出其中k个 ...

  2. DP专练1( [NOIP 2003]加分二叉树 + 太空梯 )

    我们先慢慢来 加分二叉树 题目 题解 简单讲解前序//中序//后序遍历 代码实现 太空梯 题目 题解 代码实现 加分二叉树 题目 题解 简单讲解前序//中序//后序遍历 其实说白了,这个*序就是根ro ...

  3. 4.28dp专练总结

    a 颓废了一会决定写博客 这是一篇DP专练考试总结 我真的快累死了. 时间:大概4h 6道题(丧心病狂):) T1: 数字三角形的基础上,加了若干次询问,每次废掉一个点,然后在求最优值. T2: FJ ...

  4. 初中计算机flash考试题,【信息技术中考专区】Flash操作题专练(七)!

    原标题:[信息技术中考专区]Flash操作题专练(七)! 微机中考·flash操作题 ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ 中考微机中 常用的 ...

  5. 用计算机算出你喜欢吃你喜欢的人,Go for it七年级下学期1-12单元(期末复习)句子翻译专练...

    Go for it七年级下学期1-12单元(期末复习)句子翻译专练 Unit1 1.你的笔友是哪里人? Where is your _________ _______ _________? ( pe ...

  6. 【网络流专练一】UVA五题(UVA12125,UVA11082,UVA10983,UVA1306,UVA10735)

    网络流专练 March of the Penguins 矩阵解压 Matrix Decompressing Buy one, get the rest free The K-League 混合图的欧拉 ...

  7. DP专练2 (大理石 + [ZJOI 2010]数字计数)

    你肯定以为DP专练会有很多题, 但是请考虑一下本仙女的DP码力,一次性能更几个题... 来吧,别害怕呀~~ 文章目录 大理石 题目 题解 代码实现 数字计数 题目 题解 代码实现 大理石 题目 林老师 ...

  8. 2022年证券从业资格投资顾问考试多选题专练及答案

    题库来源:优题宝公众号 2022年证券从业资格投资顾问考试多选题专练及答案,由优题宝公众号根据最新证券从业资格投资顾问考试大纲与历年证券从业资格投资顾问考试真题汇总编写,包含证券从业资格投资顾问考试常 ...

  9. 2022年证券从业资格证券市场基本法律法规考试多选题专练及答案

    题库来源:优题宝公众号 2022年证券从业资格证券市场基本法律法规考试多选题专练及答案,由优题宝公众号根据最新证券从业资格证券市场基本法律法规考试大纲与历年证券从业资格证券市场基本法律法规考试真题汇总 ...

最新文章

  1. 函数传参涉及到副本的创建与拷贝问题分析
  2. hdu 1724 Ellipse——辛普森积分
  3. 大型网站系统架构分析--转
  4. C++ 容易犯错误的模型
  5. 029_jQuery Ajax简介
  6. Heartbeat,来点真的
  7. 【Python基础】Python正则表达式入门到入魔
  8. 从17 个方面对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 等分布式消息队列
  9. python基础知识大一总结与反思_Python第一课教学设计及反思
  10. LSH︱python实现局部敏感哈希——LSHash(二)
  11. LeetCode刷题——344. 反转字符串
  12. mongoDB - 插入数据
  13. 如何制作和使用自签名证书
  14. 从高考落榜生到网络专家
  15. VC获取系统临时文件夹temp
  16. 怎么去除脸上的黄褐斑
  17. C#调用FluentFTP将文件批量上传到ftp服务器
  18. Gephi实战教程:从入门到精通
  19. Hololens拍照,录像,保存到本地,读取图片和视频
  20. 信创操作系统--统信UOS桌面版(登录与激活统信:直接登录、远程登录、锁屏、电源管理、激活)

热门文章

  1. 网易金融的“加减法”:如今仅剩支付和网络小贷
  2. 结合DDE指标来分析成本分布的重要作用
  3. Android HIDL passthrough模式与binderized
  4. iphone已停用解锁大概多少钱_iPhone 已停用?如何解锁密码?
  5. javabean,BeanUtils以及 java7的新特性 .
  6. 分屏视频怎么剪?手把手教你剪辑
  7. 什么是std::string...?怎么用
  8. 《阿甘正传》--简单中的美好
  9. 【汇正财经】12.23日盘面回顾和行情解析
  10. 集显也能硬件编码:Intel SDK 各种音视频编解码学习详解