SRM593(1-250pt,500pt)

SRM 593

DIV1 250pt

题意:有如下图所示的平面,每个六边形有坐标。将其中一些六边形染色,要求有边相邻的两个六边形不能染同一种颜色。给定哪些六边形需要染色,问最少需要多少种颜色。

解法:首先,需要0种颜色和需要1种颜色很容易判断,其次,最多需要3种颜色。易证。

   也就是说,难以判断的就是需要2种颜色还是3种颜色。假定只需要染2种颜色,然后将需要染色的六边形染色,看是否会出现矛盾。用DFS染色。

Ps:和官方题解一比,自己写的代码太麻烦了....

tag:染色

 1 /*
 2  * Author:  plum rain
 3  * score :  0
 4  */
 5 #line 11 "HexagonalBoard.cpp"
 6 #include <sstream>
 7 #include <stdexcept>
 8 #include <functional>
 9 #include <iomanip>
10 #include <numeric>
11 #include <fstream>
12 #include <cctype>
13 #include <iostream>
14 #include <cstdio>
15 #include <vector>
16 #include <cstring>
17 #include <cmath>
18 #include <algorithm>
19 
20 using namespace std;
21 
22 
23 typedef vector<string> VS;
24 VS b;
25 int n, ans, col[55][55];
26 
27 void DFS (int x, int y, int c)
28 {
29     if (!(b[x][y] == 'X' && col[x][y] == -1)) return ;
30     col[x][y] = c;
31     ans = max(ans, 1);
32     for (int i = max(0, x-1); i <= min(n-1, x+1); ++ i)
33         for (int j = max(0, y-1); j <= min(n-1, y+1); ++ j){
34             if (i-x != j-y && b[i][j] == 'X'){ 
35                 DFS (i, j, !c);
36                 ans = max(2, ans);
37                 if (col[i][j] == c){
38                     ans = 3;
39                     return ;
40                 }
41             }
42         }
43 }
44 
45 class HexagonalBoard
46 {
47     public:
48         int minColors(vector <string> board){
49          b.clear(); b = board;
50             n = b.size();
51             ans = 0;
52             memset (col, -1, sizeof(col));
53 
54             for (int i = 0; i < n; ++ i)
55                 for (int j = 0; j < n; ++ j){
56                     DFS (i, j, 0);
57                     if (ans == 3) return 3;
58                 }
59 
60             return ans;
61         }
62 };
View Code

DIV1 450pt

题意:有n只兔子,每只兔子跑一圈的时间在范围a[i] ~ b[i]。将兔子分为两组S和T,每只兔子分别跑一圈,每组所用时间等于该组所有兔子消耗时间之和。每组可能的所用时间之差的最大值为x。求x的最小值。

解法:记A为所有a[i]的和,B为所有b[i]的和,记sum = A + B。记所有属于T的兔子的a[i]之和t_a,b[i]之和为t_b,所有属于S的兔子的a[i]之和s_a,b[i]之和为s_b。

   每次将兔子分为两组之后,时间之差的最大值为max (t_b - s_a, s_b - t_a)或者max (s_b - t_a, s_b - t_a)。由于考虑到T和S是地位对等的,即如果存在T = {1,3},S = {2}的情况,也一定存在T = {2}, S = {1, 3}的情况。所以只需要求max (t_b - s_a, s_b - t_a)即可。

   max (t_b - s_a, s_b - t_a) = max (t_b - (A-t_a), (B-t_b) - t_a) = max ((t_a+t_b) - A, sum - A - (t_a+t_b)),且要使max值尽量小,则t_a + t_b 尽量接近于sum/2即可。(注意sum和A都是固定值)

   也就是说,先用一次动态规划处理出t_a + t_b的所有可能值,然后再找最接近sum/2的一个即可。

tag:math, dp, think, good

 1 /*
 2  * Author:  plum rain
 3  * score :  0
 4  */
 5 #line 11 "MayTheBestPetWin.cpp"
 6 #include <sstream>
 7 #include <stdexcept>
 8 #include <functional>
 9 #include <iomanip>
10 #include <numeric>
11 #include <fstream>
12 #include <cctype>
13 #include <iostream>
14 #include <cstdio>
15 #include <vector>
16 #include <cstring>
17 
18 using namespace std;
19 
20 #define CLR(x) memset(x, 0, sizeof(x))
21 #define out(x) cout<<#x<<":"<<(x)<<endl
22 #define tst(a) cout<<#a<<endl
23 
24 const int maxx = 1000000;
25 bool dp[maxx+5];
26 
27 class MayTheBestPetWin
28 {
29     public:
30         int calc(vector <int> A, vector <int> B){
31             CLR (dp); dp[0] = 1;
32             int sum = 0, ta = 0;
33             for (int i = 0; i < A.size(); ++ i){
34                 int s = A[i] + B[i];
35                 sum += s; ta += A[i];
36                 for (int j = maxx-s; j >= 0; -- j)
37                     if (dp[j]) dp[j+s] = 1;
38             }
39             int half = sum / 2;
40             while (!dp[half]) -- half;
41             return (sum - ta - half);
42         }
43 };
View Code
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
原文地址:https://www.cnblogs.com/plumrain/p/topcoder_srm_119.html