所谓的日常 #5 - 發矯詔諸鎮應曹公 破關兵三英戰呂布

大家期末加油~不挂科后面才能好好的做题哇=w=

div.2

CodeForces 330A Cakeminator

给一个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\n",work());
33 }
View Code

 

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\n",work());
87 }
View Code

 

posted @ 2015-12-26 20:04  zstuACM  阅读(232)  评论(0编辑  收藏  举报