题A
题意:要发明信片,有n个人,选其中的k个人来发,但是有一个规定,就是选了a的话,如果a和b关系好的,b也要寄给,所以给出m对关系好的,让你随机选k个人,求最后要发给的人数的期望,为了不输出浮点数,就将结果乘以C(n,k);
题解:期望题一般都是考虑各种情况,把所有情况都考虑清晰之后,将数加起来平均一下就可以得出答案。考虑一个人,如果选了他,那么C(n,k)中有多少种情况会导致选这个人呢?假设这个人的前面有cnt个人,也就是只要选了这cnt个人的其中一个的话,那么就会选到这个人,然后共有C(n,k)- C(n - cnt, k)种是会选到这cnt个人的,所以考虑每个点dfs一次算出cnt就可以了。
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 typedef long long ll; 9 const int maxn = 55, maxm = 1e5 + 10; 10 int n, m, k, tot; 11 int head[maxn], cnt[maxn]; 12 ll c[maxn][maxn]; 13 bool vis[maxn]; 14 15 struct Edge { 16 int v, next; 17 Edge(int v=0, int next=0) : v(v), next(next) {} 18 } edges[maxm]; 19 20 void init() { 21 c[0][0] = 1; 22 for (int i = 1; i < maxn; i++) { 23 c[i][0] = c[i - 1][0]; 24 for (int j = 1; j <= i; j++) 25 c[i][j] = c[i - 1][j] + c[i - 1][j - 1]; 26 } 27 28 memset(head, -1, sizeof head); 29 tot = 0; 30 } 31 32 void add_edge(int u, int v) { 33 edges[tot] = Edge(v, head[u]); 34 head[u] = tot++; 35 } 36 37 void dfs(int u) { 38 vis[u] = 1; 39 for (int i = head[u]; ~i; i = edges[i].next) { 40 int v = edges[i].v; 41 if (!vis[v]) dfs(v); 42 } 43 } 44 45 int main() { 46 // freopen("case.in", "r", stdin); 47 int T; 48 cin >> T; 49 while (T--) { 50 scanf("%d%d%d", &n, &m, &k); 51 init(); 52 for (int i = 0; i < m; i++) { 53 int u, v; 54 scanf("%d%d", &u, &v); 55 add_edge(v, u); 56 } 57 for (int i = 1; i <= n; i++) { 58 memset(vis, false, sizeof vis); 59 dfs(i); 60 cnt[i] = 0; 61 for (int j = 1; j <= n; j++) cnt[i] += vis[j]; 62 } 63 ll ans = 0; 64 for (int i = 1; i <= n; i++) { 65 ans += c[n][k] - c[n - cnt[i]][k]; 66 } 67 cout << ans << endl; 68 } 69 return 0; 70 }
代码君
题B
题意:定义一种数,该数的十进制表示是它的二进制表示的子串,求l,r中有多少个数满足?
题解:打表发现这种数只可能是0和1组成,那么对于这个区间的所有0和1组成的十进制数,暴力统计一下有多少个,打个表二分查找即可。
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #include <string> 11 using namespace std; 12 13 typedef long long ll; 14 const ll inf = 1e15; 15 char s[100], t[100]; 16 int dp[1 << 20], digit[100], cnt; 17 ll id[1 << 20]; 18 19 int check(int l, int r) { 20 int ret = 0; 21 for (int i = l; i <= r; i++) { 22 int ss = 0, st = 0; 23 int x = i; 24 while (x) { 25 s[ss++] = (x % 2) + ‘0‘; 26 x /= 2; 27 } 28 s[ss] = ‘\0‘; 29 reverse(s,s + ss); 30 x = i; 31 while (x) { 32 t[st++] = (x % 10) + ‘0‘; 33 x /= 10; 34 } 35 t[st] = ‘\0‘; 36 reverse(t, t + st); 37 if (strstr(s, t) != NULL) { 38 ret++; 39 } 40 } 41 return ret; 42 } 43 44 int check(ll v) { 45 ll x = v; 46 int ss = 0, st = 0; 47 while (x) { 48 s[ss++] = (x % 2) + ‘0‘; 49 x /= 2; 50 } 51 s[ss] = ‘\0‘; 52 x = v; 53 while (x) { 54 t[st++] = (x % 10) + ‘0‘; 55 x /= 10; 56 } 57 t[st] = ‘\0‘; 58 return strstr(s, t) != NULL; 59 } 60 61 void init() { 62 for (int i = 0; i < (1 << 16); i++) { 63 ll val = 0; 64 int x = i, len = 0; 65 while (x) { 66 digit[len++] = x % 2; 67 x /= 2; 68 } 69 for (int j = len - 1; j >= 0; j--) val = val * 10 + digit[j]; 70 if (check(val)) dp[i] = dp[i - 1] + 1; 71 else dp[i] = dp[i - 1]; 72 id[i] = val; 73 cnt++; 74 if (val > inf) break; 75 } 76 } 77 78 int get_ans(ll n) { 79 if (n == -1) return 0; 80 if (n == 0) return 1; 81 int len = 0; 82 ll real = 0; 83 while (n) { 84 digit[++len] = n % 10; 85 n /= 10; 86 } 87 bool flag = false; 88 for (int i = len; i > 0; i--) { 89 if (digit[i] > 1) flag = true; 90 if (flag) real = real * 10 + 1; 91 else real = real * 10 + digit[i]; 92 } 93 int pos = lower_bound(id, id + cnt, real) - id; 94 return dp[pos]; 95 } 96 97 int main() { 98 // freopen("case.in", "r", stdin); 99 init(); 100 int T; 101 cin >> T; 102 while (T--) { 103 ll l, r; 104 cin >> l >> r; 105 printf("%d\n", get_ans(r) - get_ans(l - 1)); 106 // printf("%d\n", check(l, r)); 107 } 108 return 0; 109 }
代码君
题C
题意:模拟题
题解:搞不定啊!希望有生之年能够把bug搞定吧!!
题D
题意:给你一段连续的区间长度为n,每次可以取长度为1~m的连续区间,谁取到最后的线段算赢,问你最后谁赢。
题解:这题是全场最水的题目,当然是对于学过对称博弈的大神,对于我这种渣渣当然是一个dfs打个表就交上去了。说一下正解:当m = 1的时候判一下奇偶就好了,否则的话就一定是先手必胜,因为第一个人拿了中间长度之后,然后分成均匀的两端,左边的人怎么拿,同理拿右边的就好了,这样就一定能够获胜。下面就给出我这个渣渣打表的代码吧!
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 using namespace std; 11 12 const int maxn = 210, maxk = 110; 13 int dp[maxn][maxk]; 14 15 int dfs(int n, int k) { 16 if (dp[n][k] != -1) return dp[n][k]; 17 if (k >= n) return 1; 18 bool ok = false; 19 for (int i = 1; i <= k; i++) 20 if (!dfs(n - i, k)) { 21 ok = true; break; 22 } 23 if (!ok) { 24 for (int i = 1; i <= k; i++) { 25 for (int l = 1; l < n - i; l++) { 26 int r = n - i - l; 27 if (!(dfs(l, k) ^ dfs(r, k))) ok = true; 28 if (ok) break; 29 } 30 } 31 } 32 return dp[n][k] = ok; 33 } 34 35 void init() { 36 memset(dp, -1, sizeof dp); 37 for (int i = 1; i <= 200; i++) 38 for (int j = 1; j <= 40; j++) 39 dp[i][j] = dfs(i, j); 40 } 41 42 int main() { 43 // freopen("case.in", "r", stdin); 44 init(); 45 int T; 46 cin >> T; 47 while (T--) { 48 int n, k; 49 cin >> n >> k; 50 if (dp[n][k]) puts("yes"); 51 else puts("no"); 52 } 53 return 0; 54 }
代码君(打表)
题E
题意:给你n个数,找出最大的ai % aj (i > j)
题解:这个数的范围是5e4,显然是从这里下手。然后对于一个数aj,模aj的数的结果如下:0 1 …… (ai - 1) 0 1 …… (ai - 1)这样循环地出现,所以每次我们检查一段段的看一下这一段的最大值是什么,这个显然可以用线段树进行维护,对于每个数要找n / ai次,每次logn,所以复杂度是O(nlog2n);还有一个优化,对于每个相同的数,要考虑的肯定是最后一个,因为这样考虑的数更多。
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #include <string> 11 using namespace std; 12 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 16 const int maxn = 5e4 + 10; 17 int last[maxn], _max[maxn * 4], v[maxn]; 18 19 void PU(int rt) { 20 _max[rt] = max(_max[rt * 2], _max[rt * 2 + 1]); 21 } 22 23 void build(int l, int r, int rt) { 24 _max[rt] = 0; 25 if (l == r) return; 26 int m = (l + r) / 2; 27 build(lson); 28 build(rson); 29 } 30 31 void update(int u, int d, int l, int r, int rt) { 32 if (l == r) { 33 _max[rt] = d; 34 return; 35 } 36 int m = (l + r) / 2; 37 if (u <= m) update(u, d, lson); 38 else update(u, d, rson); 39 PU(rt); 40 } 41 42 int query(int ql, int qr, int l, int r, int rt) { 43 if (ql <= l && r <= qr) { 44 return _max[rt]; 45 } 46 int m = (l + r) / 2, ret = 0; 47 if (ql <= m) ret = max(ret, query(ql, qr, lson)); 48 if (qr > m) ret = max(ret, query(ql, qr, rson)); 49 return ret; 50 } 51 52 int main() { 53 // freopen("case.in", "r", stdin); 54 int T; 55 cin >> T; 56 while (T--) { 57 int n; 58 scanf("%d", &n); 59 for (int i = 1; i <= n; i++) { 60 scanf("%d", v + i); 61 last[v[i]] = i; 62 } 63 build(0, n, 1); 64 int ans = 0; 65 for (int i = 1; i <= n; i++) { 66 if (i == last[v[i]]) { 67 int l = 0, r; 68 while (l <= n) { 69 r = min(n, l + v[i] - 1); 70 int tmp = query(l, r, 0, n, 1); 71 // printf("%d %d %d\n", l, r, tmp); 72 ans = max(ans, tmp % v[i]); 73 l += v[i]; 74 } 75 } 76 update(v[i], v[i], 0, n, 1); 77 } 78 cout << ans << endl; 79 } 80 return 0; 81 }
代码君
题F
题意:给你n * m * k的开关和灯,然后开关有一个特性,就是按下这个开关之后对应的六个方向的开关(三维)都会取反,然后问你最少按下多少个开关可以得到灯全开的状态。
题解:这道题和BC的一道div1第三题很像,只不过换成三维的了。做法就是:枚举第一层(m * k)的开关状态,然后结合第一层的灯的起始和终止(已知)状态,可以推出第二层的开关状态,最后推导出最后一层的开关状态,然后在判断能不能将最后一层的开关给点亮。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <set> 9 #include <map> 10 #include <stack> 11 using namespace std; 12 13 const int maxn = 5, dx[] = {-1, 0, 0, 0, 0, 0}, dy[] = {0, 1, -1, 0, 0, 0}, dz[] = {0, 0, 0, 1, -1, 0}, inf = 1 << 20; 14 int n, m,k; 15 int v[maxn][maxn][maxn], s[maxn][maxn][maxn]; 16 17 bool inside(int x, int y, int z) { 18 return x >= 0 && x < n && y >= 0 && y < m && z >= 0 && z < k; 19 } 20 21 int get_around(int x, int y, int z) { 22 int ret = 0; 23 for (int i = 0; i < 6; i++) { 24 int xx = x + dx[i], yy = y + dy[i], zz = z + dz[i]; 25 if (!inside(xx, yy, zz)) continue; 26 ret += s[xx][yy][zz]; 27 } 28 return ret; 29 } 30 31 bool check() { 32 for (int i = 0; i < n - 1; i++) 33 for (int j = 0; j < m; j++) 34 for (int l = 0; l < k; l++) { 35 s[i + 1][j][l] = (get_around(i, j, l) + v[i][j][l] + 1) % 2; 36 } 37 for (int j = 0; j < m; j++) 38 for (int l = 0; l < k; l++) { 39 int x = get_around(n - 1, j, l); 40 if ((x + v[n - 1][j][l]) % 2 != 1) return false; 41 } 42 return true; 43 } 44 45 int main() { 46 // freopen("case.in", "r", stdin); 47 int T; 48 cin >> T; 49 while (T--) { 50 scanf("%d%d%d", &n, &m, &k); 51 for (int i = 0; i < n; i++) 52 for (int j = 0; j < m; j++) 53 for (int l = 0; l < k; l++) 54 scanf("%d", &v[i][j][l]); 55 int ans = inf, cnt = m * k; 56 for (int i = 0; i < (1 << cnt); i++) { 57 for (int j = 0; j < cnt; j++) { 58 int x = j / k, y = j % k; 59 if (i & (1 << j)) s[0][x][y] = 1; 60 else s[0][x][y] = 0; 61 } 62 if (check()) { 63 int temp = 0; 64 for (int i = 0; i < n; i++) 65 for (int j = 0; j < m; j++) 66 for (int l = 0; l < k; l++) 67 temp += s[i][j][l]; 68 ans = min(ans, temp); 69 } 70 } 71 if (ans == inf) ans = -1; 72 cout << ans << endl; 73 } 74 return 0; 75 }
代码君
题G
题意:给你一种形状有五个格子,然后有a b c d e满足a + b + c = d + e + c,这个c是共用的,且这五个数都不能相同,问你有多少种填法。
题解:这题数据范围很小,我们可以枚举a b c然后d已经确定了,然后c有多少种取法呢,就是n - 4,累计一下即可。
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 using namespace std; 11 12 int main() { 13 // freopen("case.in", "r", stdin); 14 int T; 15 cin >> T; 16 while (T--) { 17 int n, ans = 0; 18 scanf("%d", &n); 19 for (int i = 1; i <= n; i++) 20 for (int j = 1; j <= n; j++) if (i != j) { 21 int s = i + j; 22 for (int k = 1; k <= s; k++) if (k >= 1 && k <= n && k != i && k != j && k != s - k && s - k >= 1 && s - k <= n && s - k != i && s - k != j) { 23 ans += (n - 4); 24 } 25 } 26 cout << ans << endl; 27 } 28 return 0; 29 }
代码君
题H
题意:给你n和m,然后求有多少个满足下列条件的长度为m的序列
(1)序列是非递减的
(2)序列的数的范围是【1,n】
(3)满足A[1] * A[2] * ...... * A[m] = lcm(A[1], A[2], ....,A[m]) * gcd(A[1], A[2],...A[m])
题解:实际上要想lcm * gcd必须是这m个数是互素的,所以题目就是求长度为m的互素的非递减序列有多少种?分析一下数据规模,n为100,里面的素因子种类有25个,我们观察可以发现,一个数存在两种素因子的最小的是50(5和2),在后面的数如果有两个素因子的话一定是50以内的,所以我们就可以用dp(i, j, k)表示长度为i的序列,考虑j这个数作为末尾,素因子的状态为k,由于50以内有15个素因子,所以k的取值为(1 << 15);然后就是转移了,显然枚举j + 1 …… 100作为末尾,但前提是对k状态没有冲突,这个要写一个函数来判断,然后加进这个数之后状态有什么变化,也要写个函数。对于这两个函数的所有结果用两个数组分别保存,最后记得统计一下答案即可。
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <iostream> 4 #include <cstring> 5 #include <algorithm> 6 #include <cmath> 7 #include <vector> 8 using namespace std; 9 10 typedef long long ll; 11 const int mod = 1e9 + 7; 12 int dp[30][110][1 << 15], id[110], prime[110], f[110], to[110][1 << 15]; 13 int ans[40][140]; 14 bool vis[110][1 << 15]; 15 16 17 bool check(int x, int s) { 18 for (int i = 0; i < 15; i++) if (x % prime[i] == 0) { 19 if (s & (1 << i)) return false; 20 } 21 return true; 22 } 23 24 int get_status(int x, int s) { 25 for (int i = 0; i < 15; i++) if (x % prime[i] == 0) { 26 s |= (1 << i); 27 } 28 return s; 29 } 30 31 void init() { 32 id[0] = id[1] = 1; 33 for (int i = 2; i <= 50; i++) if (!id[i]) 34 for (int j = i + i; j <= 50; j += i) id[j] = 1; 35 int cnt = 0; 36 for (int i = 2; i <= 50; i++) 37 if (!id[i]) prime[cnt++] = i; 38 // for (int i = 0; i < cnt; i++) cout << prime[i] << ‘ ‘; 39 // cout << cnt << endl; 40 for (int x = 2; x <= 100; x++) 41 for (int y = 0; y < (1 << 15); y++) if (check(x, y)) { 42 vis[x][y] = 1; 43 to[x][y] = get_status(x, y); 44 } 45 } 46 47 void add(int& a, int b) { 48 a += b; 49 if (a >= mod) a -= mod; 50 } 51 52 void slove() { 53 dp[0][0][0] = 1; 54 for (int i = 0; i < 25; i++) { 55 for (int j = i; j <= 100; j++) { 56 for (int k = 0; k < (1 << 15); k++) if (dp[i][j][k]) { 57 // cout << i << ‘ ‘ << j << ‘ ‘ << k << endl; 58 for (int x = max(2, j + 1); x <= 100; x++) if (vis[x][k]) 59 add(dp[i + 1][x][to[x][k]], dp[i][j][k]); 60 } 61 } 62 } 63 for (int i = 1; i <= 25; i++) { 64 for (int j = i; j <= 100; j++) { 65 for (int k = 0; k < (1 << 15); k++) { 66 add(ans[i][j], dp[i][j][k]); 67 } 68 } 69 } 70 } 71 72 int get_ans(int n, int m) { 73 int ret = 1; 74 for (int i = 1; i <= min(25, m); i++) 75 for (int j = i; j <= min(100, n); j++) 76 add(ret, ans[i][j]); 77 return ret; 78 } 79 80 int main() { 81 // freopen("case.in", "r", stdin); 82 init(); 83 slove(); 84 int T; 85 scanf("%d", &T); 86 while (T--) { 87 int n, m; 88 scanf("%d%d", &n, &m); 89 if (m == 2) printf("%d\n", n * (n + 1) / 2); 90 else { 91 printf("%d\n", get_ans(n, m)); 92 } 93 } 94 return 0; 95 }
代码君
题I
题意:给你一个四边形,让你切成两个三角形,然后组成的三角形周长最大。
题解:首先要看这个四边形是不是凸的。如果是凸的,直接枚举两种情况,如果不是,那么就找出那个导致四边形是凹的的点,然后直接和另外一个点分成两个三角形即可。
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #include <string> 11 using namespace std; 12 13 const double eps = 1e-8; 14 15 int sgn(double x) { 16 if (fabs(x) < eps) return 0; 17 if (x < 0) return -1; 18 return 1; 19 } 20 21 struct Point { 22 double x, y; 23 Point() {} 24 Point(double _x, double _y) { 25 x = _x; y = _y; 26 } 27 void input() { 28 scanf("%lf%lf", &x, &y); 29 } 30 double operator ^ (const Point& b) const { 31 return x * b.y - y * b.x; 32 } 33 Point operator - (const Point& b) const { 34 return Point(x - b.x, y - b.y); 35 } 36 double dist(Point b) { 37 return sqrt((x - b.x) * (x - b.x) + (y - b.y) * (y - b.y)); 38 } 39 double operator * (const Point& b) const { 40 return x * b.x + y * b.y; 41 } 42 }; 43 44 struct Polygon { 45 int n; 46 Point p[5]; 47 int relationpoint(Point q) { 48 int cnt = 0; 49 for (int i = 0; i < n; i++) { 50 int j = (i + 1) % n; 51 int k = sgn((q - p[j]) ^ (p[i] - p[j])); 52 int u = sgn(p[i].y - q.y); 53 int v = sgn(p[j].y - q.y); 54 if (k > 0 && u < 0 && v >= 0) cnt++; 55 if (k < 0 && v < 0 && u >= 0) cnt--; 56 } 57 return cnt != 0; 58 } 59 }; 60 61 Polygon poly[10]; 62 Point p[5]; 63 64 int main() { 65 // freopen("case.in", "r", stdin); 66 int T; 67 cin >> T; 68 while (T--) { 69 int n = 4; 70 for (int i = 0; i < n; i++) p[i].input(); 71 for (int i = 0; i < n; i++) { 72 int cnt = 0; 73 for (int j = 0; j < n; j++) if (i != j) poly[i].p[cnt++] = p[j]; 74 poly[i].n = cnt; 75 } 76 int t = -1; 77 for (int i = 0; i < n; i++) { 78 if (poly[i].relationpoint(p[i])) { t = i; break; } 79 } 80 double ans = 0; 81 for (int i = 0; i < 4; i++) ans += p[i].dist(p[(i + 1) % n]); 82 if (t == -1) { 83 ans += max(p[0].dist(p[2]) * 2, p[1].dist(p[3]) * 2); 84 } else { 85 ans += p[t].dist(p[(t + 2) % 4]) * 2; 86 } 87 printf("%.3lf\n", ans); 88 } 89 return 0; 90 }
代码君
题J
题意:一开始给你一个人,坐标和速度,然后给你目标点,然后在给你n个可以辅助的人,做斜抛运动,然后问你最短时间到目标点。
题解:设这个时间为t,然后有
L = Vx t
Vy = g(t/2)
然后联立成一个一元二次方程再判有没有解即可,无解就说明这两个点是inf,注意每个人都有一个速度,所以是有向边。在最后跑一次最短路就行了。
1 /*zhen hao*/ 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <cmath> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #include <string> 11 using namespace std; 12 13 typedef long long ll; 14 const int maxn = 20, maxm = 1e3 + 10; 15 const double inf = 1e10; 16 double dist[maxn]; 17 int n, tot, head[maxn], done[maxn]; 18 19 struct Point { 20 double x, y, v; 21 void input() { 22 scanf("%lf%lf%lf", &x, &y, &v); 23 } 24 double dist(Point o) { 25 double a = 25.0, b = v * v, c = (x - o.x) * (x - o.x) + (y - o.y) * (y - o.y); 26 double delta = b * b - 4 * a * c; 27 if (delta < 0) return inf; 28 double x1 = (b - sqrt(delta)) / (2.0 * a), x2 = (b + sqrt(delta)) / (2.0 * a); 29 if (x1 > 0 && x2 > 0) return sqrt(min(x1, x2)); 30 if (x1 < 0 && x2 < 0) return inf; 31 return sqrt(max(x1, x2)); 32 } 33 } p[maxn]; 34 35 struct Edge { 36 int v; 37 double w; 38 int next; 39 Edge(int v=0, double w=0, int next=0) : v(v), w(w), next(next) {} 40 } edges[maxm]; 41 42 struct Node { 43 double d; 44 int u; 45 Node(double d=0, int u=0) : d(d), u(u) {} 46 bool operator < (const Node& o) const { 47 return d > o.d; 48 } 49 }; 50 51 void init() { 52 tot = 0; 53 memset(head, -1, sizeof head); 54 } 55 56 void add_edge(int u, int v, double w) { 57 edges[tot] = Edge(v, w, head[u]); 58 head[u] = tot++; 59 } 60 61 void dijkstra() { 62 for (int i = 0; i <= n; i++) dist[i] = inf; 63 memset(done, 0, sizeof done); 64 dist[0] = 0; 65 priority_queue<Node> pq; 66 pq.push(Node(0, 0)); 67 while (!pq.empty()) { 68 Node r = pq.top(); pq.pop(); 69 int u = r.u; 70 if (done[u]) continue; 71 done[u] = 1; 72 for (int i = head[u]; ~i; i = edges[i].next) { 73 Edge& e = edges[i]; 74 if (dist[e.v] > dist[u] + e.w) { 75 dist[e.v] = dist[u] + e.w; 76 pq.push(Node(dist[e.v], e.v)); 77 } 78 } 79 } 80 } 81 82 83 int main() { 84 // freopen("case.in", "r", stdin); 85 int T; 86 cin >> T; 87 while (T--) { 88 p[0].input(); 89 scanf("%d", &n); 90 for (int i = 1; i <= n; i++) p[i].input(); 91 ++n; 92 scanf("%lf%lf", &p[n].x, &p[n].y); 93 94 init(); 95 for (int i = 0; i < n; i++) 96 for (int j = 0; j <= n; j++) if (i != j) { 97 double w = p[i].dist(p[j]); 98 if (w != inf) add_edge(i, j, w); 99 } 100 dijkstra(); 101 printf("%.3lf\n", dist[n]); 102 } 103 return 0; 104 }
代码君
最后一个福利:题目 + 洲神题解