220421总结
220421总结
T1 最短路径问题
题目都这么写了那肯定是最短路啊。。。
最开始写的 \(\operatorname{Dijkstra}\) ,莫名其妙挂了...
改成 \(\operatorname{Floyd}\) 就莫名其妙过了
???
T2 质数和分解
其实确实考虑过打表来着
先把小于 \(200\) 的质数提前筛出来了
算是完全背包问题吧
设 \(f(i)\) 表示 \(i\) 的分解方案数,\(\text{p}_j\) 表示第 \(j\) 个质数
那么 \(f(i)=\displaystyle\sum_{j=1}^{\text{p}_j<i}f(i-\text{p}_j)\)
dp[0] = 1;
for(int i = 0;i<=46;i++){
for(int j = prime[i];j<=200;j++){
dp[j] += dp[j - prime[i]];
}
}
然后忽略了
每一行存放一个自然数
就这样才挂了一个点
T3 牛的旅行
怎么又是图论(
存图什么的就不说了,给了邻接矩阵不用白不用(
先要跑一遍多源最短路,找出各个牧区之间的最短路
inline void Floyd(){
for(int k = 1;k<=N;k++){
for(int i = 1;i<=N;i++){
for(int j = 1;j<=N;j++){
dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
}
用并查集来判断两个牧区在不在同一个牧场
int fa[maxN];
int find(int x){
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
用最短路去求每个牧场的直径和每个点可以到达的最远的牧区
for(int i = 1;i<=N;i++){
maxD[i] = 0;
for(int j = 1;j<=N;j++){
if(find(i) == find(j)){
maxD[i] = max(maxD[i],dis[i][j]);
}
}
int x = find(i);
AD[x] = max(AD[x],maxD[i]);
}
扫一遍所有的牧区对,如果这两个牧区 \(i,j\) 不在同一个牧场,求添加一条边 \((i,j)\) 后形成的牧场的直径
求新形成牧场的直径为两个牧场和 \(\text{maxd}_i+\text{maxd}_j+dis(i,j)\) 的最大值
答案为新直径的最小值
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxN = 300;
const double INF = 1e15;
int N;
int P[maxN][2];
double AD[maxN];
double maxD[maxN];
double dis[maxN][maxN];
inline double Len(int A[],int B[]){
return sqrt((A[0]-B[0])*(A[0]-B[0])+(A[1]-B[1])*(A[1]-B[1]));
}
int fa[maxN];
int find(int x){
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
inline void Floyd(){
for(int k = 1;k<=N;k++){
for(int i = 1;i<=N;i++){
for(int j = 1;j<=N;j++){
dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
}
int main(){
scanf("%d",&N);
for(int i = 1;i<=N;i++) scanf("%d%d",&P[i][0],&P[i][1]);
for(int i = 1;i<=N;i++) fa[i] = i;
for(int i = 1;i<=N;i++){
char S[maxN];
scanf("%s",S);
for(int j = 1;j<=N;j++){
if(i == j) dis[i][j] = 0;
if(S[j-1] == '0'){
dis[i][j] = INF;
continue;
}
int x,y;
x = find(i);
y = find(j);
if(x != y) fa[y] = x;
dis[i][j] = Len(P[i],P[j]);
}
dis[i][i] = 0;
}
Floyd();
for(int i = 1;i<=N;i++){
maxD[i] = 0;
for(int j = 1;j<=N;j++){
if(find(i) == find(j)){
maxD[i] = max(maxD[i],dis[i][j]);
}
}
int x = find(i);
AD[x] = max(AD[x],maxD[i]);
}
double r1,r2=INF;
for(int i = 1;i<=N;i++){
for(int j = 1;j<=N;j++){
int x = find(i);
int y = find(j);
if(x != y){
double L = maxD[i] + maxD[j] + Len(P[i],P[j]);
r1 = max(L,max(AD[x],AD[y]));
r2 = min(r1,r2);
}
}
}
printf("%.6lf\n",r2);
return 0;
}
T4 逃亡的准备
多重背包
为了保险用了二进制拆分