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)$
1 2 3 4 5 6
| 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 牛的旅行
怎么又是图论(
存图什么的就不说了,给了邻接矩阵不用白不用(
先要跑一遍多源最短路,找出各个牧区之间的最短路
1 2 3 4 5 6 7 8 9
| 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]); } } } }
|
用并查集来判断两个牧区在不在同一个牧场
1 2 3 4 5
| int fa[maxN];
int find(int x){ return x == fa[x] ? x : (fa[x] = find(fa[x])); }
|
用最短路去求每个牧场的直径和每个点可以到达的最远的牧区
1 2 3 4 5 6 7 8 9 10
| 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)$ 的最大值
答案为新直径的最小值
点击查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| #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 逃亡的准备
多重背包
为了保险用了二进制拆分