1、水题,略。
2、用到了状态压缩
注释清楚http://blog.csdn.net/hhaile/article/details/8209474
#include <iostream> #include <string> #include <vector> #include <cstdlib> #include <map> #include <algorithm> using namespace std; #define INF 999999 class ICPCBalloons { public: int minRepaintings(vector<int> balloonCount, string balloonSize, vector<int> maxAccepted); }; int cmp(int a, int b) { return a > b; } // 在不考虑大小的情况下 int fun(vector<int> a, vector<int> b) { //a为气球,b为题 int len1 = a.size(); int len2 = b.size(); int sum1 = 0, sum2 = 0; for (int i = 0; i < len1; i++) sum1 += a[i]; for (int j = 0; j < len2; j++) sum2 += b[j]; if (sum1 < sum2) //如果气球数目比题数目小,无解 return INF; int ans = 0; //否则肯定有可行解 for (int i = 0; i < len2; i++) { if (i < len1) //从大到小一一对应 { if (a[i] < b[i]) //如果当前颜色的气球不够过题数,肯定要从其他颜色气球拿,至于从哪拿不用考虑,肯定是有解的 ans += b[i] - a[i]; } else { ans += b[i]; //如果颜色种数少于题目种数,多余的题目种数肯定要用前面剩下的气球填满。 } } return ans; } int ICPCBalloons::minRepaintings(vector<int> balloonCount, string balloonSize, vector<int> maxAccepted) { int len1 = balloonCount.size(); int len2 = maxAccepted.size(); vector<int> M, L; for (int i = 0; i < len1; i++) { if (balloonSize[i] == 'M') M.push_back(balloonCount[i]); else L.push_back(balloonCount[i]); } sort(M.begin(), M.end(), cmp); sort(L.begin(), L.end(), cmp); int ans = INF; for (int i = 0; i < (1 << len2); i++) { vector<int> Mq, Lq; for (int j = 0; j < len2; j++) { if ((i >> j) & 1) Mq.push_back(maxAccepted[j]); else Lq.push_back(maxAccepted[j]); } sort(Mq.begin(), Mq.end(), cmp); sort(Lq.begin(), Lq.end(), cmp); ans = min(ans, fun(M, Mq) + fun(L, Lq)); } if (ans == INF) return -1; else return ans; }
3、大概思路就是根据某条路径将图分成两个子图A B,
A中的居民个数和城市个数分别为pa和ca,
B中的居民个数和城市个数分别为pb和cb,
总的居民个数和城市个数分别为ps和cs,
则某条道路被使用的期望则为 (cb/(cs-1))^pa + (ca/(cs-1))^pb
对每一条路径求期望,将期望求和则可。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <map> 6 #include <algorithm> 7 #include <queue> 8 using namespace std; 9 class FoxAndTouristFamilies { 10 public: 11 int dfs(vector<int> A, vector<int> B, vector<int> population, int num_road, 12 int start, int& citynum, int forbid) { //forbid保证断开路径 13 citynum = 0; 14 queue<int> myque; 15 myque.push(start); 16 vector<int> in(num_road + 1, 0); 17 in[start] = 1; 18 in[forbid] = -1; 19 while (!myque.empty()) { 20 int cur = myque.front(); 21 myque.pop(); 22 for (int i = 0; i < num_road; i++) { 23 if (A[i] == cur && in[B[i]] == 0) { 24 myque.push(B[i]); 25 in[B[i]] = 1; 26 } 27 if (B[i] == cur && in[A[i]] == 0) { 28 myque.push(A[i]); 29 in[A[i]] = 1; 30 } 31 } 32 33 } 34 35 int res = 0; 36 for (int i = 0; i < num_road + 1; i++) { 37 if (in[i] == 1) { 38 res += population[i]; 39 citynum++; 40 } 41 } 42 return res; 43 } 44 double expectedLength(vector<int> A, vector<int> B, vector<int> f) { 45 int numCity = A.size() + 1; //城市个数 46 int num_road = A.size(); //道路个数 47 int total = f.size(); //居民个数 48 vector<int> population(numCity, 0); 49 vector<int> numSubCity(num_road, 1); //子树上的城市个数 50 for (int i = 0; i < f.size(); ++i) { //计算每个city的人数 51 population[f[i]]++; 52 } 53 54 vector<int> num_way(num_road, 0); //子树上的居民个数 55 for (int i = 0; i < num_road; i++) { 56 num_way[i] = dfs(A, B, population, num_road, B[i], numSubCity[i], 57 A[i]); 58 } 59 60 double res = 0.0; 61 for (int i = 0; i < num_road; i++) { 62 double fm = numCity - 1; //每个家庭的选择个数 63 64 double exp = 1; //记录某条路径被选中的期望 65 66 double rate1 = (numCity - numSubCity[i]) / fm; 67 for (int j = 0; j < num_way[i]; j++) { 68 exp = exp * rate1; 69 } 70 71 double rate2 = numSubCity[i] / fm; 72 int remain = total - num_way[i]; 73 for (int j = 0; j < remain; j++) { 74 exp = exp * rate2; 75 } 76 77 res += exp; 78 } 79 return res; 80 } 81 82 };
DIV1-2、今天了解了一些sg函数的知识,很有收获,原来编程之美上的NIM游戏有这么有趣的原理。
参考代码:http://www.cppblog.com/hanfei19910905/archive/2012/11/21/195471.aspx?opt=admin
sg函数相关知识:http://download.csdn.net/download/lhb807949392/3500177
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <map> 6 #include <algorithm> 7 #include <queue> 8 #include <cmath> 9 using namespace std; 10 const int N = 55; 11 int P[N], n, dp[N]; 12 vector<int> G[N]; 13 inline void setc(int p, int c) { 14 P[c] = p; 15 G[p].push_back(c); 16 } 17 bool ispar(int s, int p) { //判断p是不是s的父亲节点 18 while (s != -1) { 19 if (s == p) 20 return 1; 21 s = P[s]; 22 } 23 return 0; 24 } 25 int dfs(int u) { 26 int &ans = dp[u]; 27 if (ans != -1) { 28 return ans; 29 } 30 bool vis[101] = { 0 }; 31 for (int i = 0; i < n; i++) 32 if (ispar(i, u)) { //如果i是u的儿子节点 33 //计算当前局面下的sg值 34 int v = i, last = -1, sg = 0; 35 while (v != P[u]) { 36 for (int j = 0; j < G[v].size(); j++) 37 if (G[v][j] != last) 38 sg ^= dfs(G[v][j]); 39 last = v; 40 v = P[v]; 41 } 42 vis[sg] = 1; 43 //标记sg值 44 } 45 for (int i = 0; i < 101; i++) 46 if (!vis[i]) { 47 ans = i; 48 break; 49 } 50 return ans; 51 } 52 double dis(int x0, int y0, int x1, int y1) { 53 return sqrt(1.0 * (x0 - x1) * (x0 - x1) + 1.0 * (y0 - y1) * (y0 - y1)); 54 } 55 56 class CirclesGame { 57 public: 58 string whoCanWin(vector<int> x, vector<int> y, vector<int> r) { 59 memset(P, -1, sizeof(P)); 60 memset(dp, -1, sizeof(dp)); 61 n = x.size(); 62 for (int i = 0; i < n; i++) { 63 int s = -1; 64 for (int j = 0; j < n; j++) 65 if (j != i 66 && 1.0 * (r[j] - r[i]) > dis(x[i], y[i], x[j], y[j])) { //i是否在j中 67 if (s == -1 || r[j] < r[s]) 68 s = j; 69 } 70 if (s != -1) { //包含i的最小的圆 71 setc(s, i); 72 } 73 } 74 int ans = 0; 75 for (int i = 0; i < n; i++) 76 if (-1 == P[i]) 77 ans ^= dfs(i); 78 79 return ans ? "Alice" : "Bob"; 80 } 81 };