2019暑期集训第一周小结
E、剪枝搜索
特点:
一轮搜索完成后,清空标记数组的问题
在搜索的过程中,需要借助标记数组,来防止重复的访问。
之前采取的方法是,通过标记为1,表示该值被访问过。
但是这样做不适合多轮的搜索,因为每轮搜索结束后,都需要重新把标记数组清零。
解决:每轮搜索都设置一个唯一的值(不再局限于1和0)
标记数组的本质是通过设置不同的数字,来区分两块数据。
一个区域里面的所有的点的答案值相同,如何赋值的问题
-
通过搜索该区域里面所有的点,得到一个答案。同时,根据题意,这个答案也是同区域里面其他点的答案。因此,希望采用记忆化的思想,当查询其他点时,直接输出答案。
-
联想到上一个问题中提到的标记数组,恰好,标记数组具有这样的特性,因为每轮搜索都相当于完成一个区域的查询,因此 通过查询该点的 标记数组所代表的值 ,来判断是否需要重新搜索。
M题
- 无向图
无向图存边的数组容量开二倍的问题
虽然题目只给出了一条边,但是因为是无向图,所以要正反处理两次,因此存边的数组容量应该开二倍。
- 链式前向星
B题 特殊的BFS边界条件判断
背景
因为题目要求玩家只要最后可以安全到达最后一列即可,设共有n列,根据题目规则,因为玩家只能走值为“.”的格,且玩家到达第n列,第n+1列,第n+2列都输出“YES”。 因此,如果不对第n+1列,第n+2列做预处理的话,前后条件就发生了冲突。
教训
- 注意辨别if前后的判断条件是否会有冲突。
- 想一想地图之外的点如果也是可达点的话,是否需要与地图内的那些可达点统一格式。
C题 构造
题目
有颜色分别为A B C D的四种颜色块,他们之间通过互相交融,使得每种颜色都能有特定数量的联通块。
解题思想
由小及大
- 先看两个颜色之间
- 先看两种颜色各形成一个连通块,会是类似于条形磁铁的样子,A全部在左边,B全部在右边,井水不犯河水。
- 再看要求连通数为 2 1 ,则把一个A放到B中。
- 发现四个颜色的组合,其实也可以用这种思想。
D题 数学、构造
- 通过点或边的个数,计算平行四边形的个数。
- 通过平行四边形的定义,判断怎样搜索可以查询平行四边形的所有组合方式。
这段时间做搜索做的,光想着怎么搜索来找到全部平行四边形的个数,忘记了可以直接用数学方法来计算。
H题 DP之维护最长距离
发现问题的关键,即一个点删除的条件是 到达该点的最长距离是否大于该点的权值,因此应当维护这么一个数组con,con[i]代表到达点i的最长路径的长度。
k叉树 已知结点个数,判断树的深度
//树型结构,已知结点数求完全k叉树的深度
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0);
const double e=exp(1);
//const int MAXN =2e5+10;
const int N =332748118;
int main()
{
LL i,p,j,n,t,k;
LL deep,head,mid,live,two,ans,ceng;
double ce;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld",&k,&n);
if(k == 2 && n == 1)
{
ans = 0;
}
else
{
head = 1;
mid = 1;
for(i = 0; i <= 100000; i++)
{
ceng = i + 1; //当前的层数
if(head == n) // ceng层的满k叉树
{
ans = i * 2;
break;
}
else if(head > n) // ceng-1层满的k叉树
{
//live = i;
//deep = i - 1;
// cout << " ** " << mid << " ceng :" << ceng << endl;
// cout << " head: " << head << endl;
// head - n 少的结点数 判断少于一半
if( mid - (head - n) > (mid / k) ) // head 当前ceng满k叉树应该有的总结点数
{
// mid 当前ceng应该有的结点数
ans = i * 2;
}
else
{
ans = (i - 1) * 2 + 1;
}
break;
}
mid *= k; // k的ceng次幂
head += mid;
}
}
printf("%lld\n",ans);
}
return 0;
}