大家期末加油~不挂科后面才能好好的做题哇=w=
div.2
给一个r(<=10)行c(<=10)列的矩形蛋糕,每次你会选择一行或一列全部吃掉。有些位置有草莓,然而你不想吃草莓,问最多能吃到多少蛋糕。
如果我们吃了a行b列的话,可以这么算:先数a * m个,再数b * n个,然后把重复算的部分去掉,也就是a * b个。
或者另外开一个标记数组,把吃掉的位置标记一下也是可以的。怎么写高兴怎么来。
1 #include <stdio.h> 2 3 const int N = 10 + 5; 4 int n,m; 5 char str[N][N]; 6 bool A[N],B[N]; 7 8 int work() { 9 for (int i = 0; i < n; ++ i) { 10 for (int j = 0; j < m; ++ j) { 11 if (str[i][j] == 'S') { 12 A[i] = true; 13 B[j] = true; 14 } 15 } 16 } 17 int a = 0,b = 0; 18 for (int i = 0; i < n; ++ i) 19 if (A[i] == false) 20 a ++; 21 for (int i = 0; i < m; ++ i) 22 if (B[i] == 0) 23 b ++; 24 25 return a * m + b * n - a * b; 26 } 27 28 int main() { 29 scanf("%d%d",&n,&m); 30 for (int i = 0; i < n; ++ i) 31 scanf("%s",str[i]); 32 printf("%d ",work()); 33 }
div.1
CodeForces 543B Destroying Roads
给一张n(<=3000)个点的无向连通图,边权为1。问删掉最多的边,使得从点s1到点t1距离不超过l1,从点s2到点t2距离不超过l2。
容易知道如果只有一组限制条件的话(s1,t1,l1),那么只要把s1到t1的最短路必须经过的边保留下来就可以了。
对于两组限制条件,s1到t1的路径会与s2到t2的路径有重复一部分。那么我们就枚举重复部分的起点和终点,就可以按上面只有一组条件的情况来做了。O(n^2)。
1 #include <bits/stdc++.h> 2 using LL = long long ; 3 4 const int N = 3000 + 5; 5 const int INF = 0x3f3f3f3f; 6 7 std::vector<int> edges[N]; 8 9 int n,m; 10 int points[4],l[2]; 11 int dis[N][N]; 12 13 int bfs(int source,int *dis) { 14 std::queue<int> que; 15 std::fill(dis,dis + n,INF); 16 dis[source] = 0; 17 que.push(source); 18 while (!que.empty()) { 19 int u = que.front(); 20 que.pop(); 21 for (int v : edges[u]) { 22 if (dis[v] == INF) { 23 dis[v] = dis[u] + 1; 24 que.push(v); 25 } 26 } 27 } 28 } 29 30 int work() { 31 for (int i = 0; i < n; ++ i) { 32 bfs(i,dis[i]); 33 } 34 if (dis[points[0]][points[1]] > l[0] 35 || dis[points[2]][points[3]] > l[1]) { 36 return -1; 37 } 38 int answer = dis[points[0]][points[1]] 39 + dis[points[2]][points[3]]; 40 for (int i = 0; i < n; ++ i) { 41 for (int j = 0; j < n; ++ j) { 42 if (dis[points[0]][i] + dis[i][j] + dis[j][points[1]] 43 <= l[0] 44 && 45 dis[points[2]][i] + dis[i][j] + 46 dis[j][points[3]] 47 <= l[1]) { 48 answer = std::min(answer, 49 dis[points[0]][i] 50 + dis[i][j] 51 + dis[j][points[1]] 52 + dis[points[2]][i] 53 + dis[j][points[3]]); 54 } 55 if (dis[points[0]][i] + dis[i][j] + dis[j][points[1]] 56 <= l[0] 57 && 58 dis[points[2]][j] + dis[i][j] 59 + dis[i][points[3]] 60 <= l[1]) { 61 answer = std::min(answer, 62 dis[points[0]][i] 63 + dis[i][j] 64 + dis[j][points[1]] 65 + dis[points[2]][j] 66 + dis[i][points[3]]); 67 } 68 } 69 } 70 return m - answer; 71 } 72 73 int main() { 74 scanf("%d%d",&n,&m); 75 for (int i = 0; i < m; ++ i) { 76 int a,b; 77 scanf("%d%d",&a,&b); a --; b --; 78 edges[a].push_back(b); 79 edges[b].push_back(a); 80 } 81 scanf("%d%d%d%d%d%d",points + 0,points + 1,l + 0, 82 points + 2,points + 3,l + 1); 83 for (int i = 0; i < 4; ++ i) { 84 points[i] --; 85 } 86 printf("%d ",work()); 87 }