本人2023年上岸浙大计算机学院专硕,无算法竞赛基础在初试后准备机试最后拿到了95分。学习和刷题过程中总结了一些板子题,发到csdn平台上供后来人借鉴。若有错误请指正。
感谢acwing平台的y总,他的算法思想和代码风格给了我备考过程中最大的帮助。
1.Dijkstra:两层循环,内部先选最小距离点,再标记“已访问”,最后更新距离数组
void dijkstra(int root)
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
dist[root]=0;
for (int i=0;i<n;i++)
{
int t=-1;
for (int j=1;j<=n;j++)
{
if (!st[j] && (t==-1 || dist[j]<dist[t]))
t=j;
}
st[t]=1;
for (int j=1;j<=n;j++)
{
if (dist[t]+graph[t][j]<dist[j])
dist[j]=dist[t]+graph[t][j];
}
}
}
2.bfs+层次标记(dist数组写距离,每层在刚刚弹出的元素里面+1,刚好借助这个模板熟练bfs)
vector<int> graph[N];
int dist[N];
int bfs(int root,int aim)
{
memset(dist,-1,sizeof dist);
dist[root]=0;
queue<int> q;
q.push(root);
while (q.size())
{
int t=q.front();
q.pop();
for (auto a:graph[t])
{
if (dist[a]==-1)
{
q.push(a);
dist[a]=dist[t]+1;
}
}
}
return dist[aim];
}
3.树的构建(in+post为例),in+pre类似(取pl点为根),分治法递归
int post[N],tree[N],le[N],ri[N];
unordered_map<int,int> pos;
int construct(int il,int ir,int pl,int pr)
{
int k=pos[post[pr]];
if (il<k)
le[k]=construct(il,k-1,pl,pl+(k-1-il));
else
le[k]=-1;
if (k<ir)
ri[k]=construct(k+1,ir,pr-1-(ir-k-1),pr-1);
else
ri[k]=-1;
return k;
}
4.并查集,收录两个操作:union&find
void union(int a,int b)
{
int pa=find(a);
int pb=find(b);
if (pa!=pb)
p[pa]=pb;
}
int find(int x)
{
if (x!=p[x])
p[x]=find(p[x]);
return p[x];
}
5.二分法
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
while (l<r)
{
int mid=l+r >> 1;
if (check(mid)) r=mid; // check()判断mid是否满足性质
else l=mid+1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
while (l<r)
{
int mid=l+r+1 >> 1;
if (check(mid)) l=mid;
else r=mid-1;
}
return l;
}
//浮点数:注意不要用等号
double bsearch_3(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
6.dfs+路径储存(如果不选择输出,也可以压入二级vector),注意“恢复现场”的递归思想
int n;
int path[N];
bool st[N];
void dfs(int u)
{
if (u==n)
{
for (int i=0;i<n;i++)
cout<<path[i];
cout<<endl;
return;
}
for (int i=1;i<=n;i++)
{
if (!st[i])
{
path[u]=i;//路径写入
st[i]=1;//标记“已访问”
dfs(u+1);//递归
st[i]=0;//恢复现场
}
}
}