SRM 561 DIV2 DIV1

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 };
原文地址:https://www.cnblogs.com/kakamilan/p/2782936.html