http://mlz000.github.io/2015/07/15/srm-539/

250


Description:

从若干个盒子中随意选择几个装石头。每一个盒子容量都有上下限,一旦选择使用某个盒子,那么填装的石头数必须在该盒子的上下限容量之间。假设终于填装的石头总数为x。那么符合条件x>9000x有多少个?
数据规模:盒子总数[1,15], 盒子容量[1,106]

Solution

盒子总数15非常easy想到枚举状态,把每一个的上下限存一下。排个序统计一下答案就可以。

Code

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
typedef long long LL;
typedef pair<int, int> pii;
const int M = 9000;
vector<pii> a;
class Over9000Rocks {
    public:
        int countPossibilities(vector <int> lowerBound, vector <int> upperBound) {
            int n = lowerBound.size();
            for (int i = 0; i < 1 << n; ++i) {
                int l = 0, r = 0;
                for (int j = 0; j < n; ++j) {
                    if (i >> j & 1) {
                        l += lowerBound[j];
                        r += upperBound[j];
                    }
                }
                l = max(l, M + 1);
                if (l <= r) a.pb(mp(l, r));
            }
            sort(a.begin(), a.end());
            int R = 0, ans = 0;
            for (int i = 0; i < a.size(); ++i) {
                if (a[i].F > R) ans += a[i].S - a[i].F + 1;
                else if (a[i].S > R)    ans += a[i].S - R;
                R = max(R, a[i].S);
            }
            return ans;
        }
};

550


Description

目大意:给定一张图。有T个点,如今有 n 个人要从0号点分别走到 1 ~ n 号点,每一个人都是沿着自己最短路径走(有多条最短路径则可随意选一条)。假设在到达终点之前。有个人单独行动,则觉得这个人是处在危急中的(仅仅有一个人经过某条边)。问n个人该怎么走使得处在危急中的人数最少。

Solution

能够想到,假设一个人的是安全的话那么他的最短路径一定能够被还有一个人全然覆盖,这样我们把相互能够覆盖的建个图。求匹配即是答案。

Code

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
typedef long long LL;
typedef pair<int, int> pii;
const int N = 55;
int d[N][N], f[N][N], l[N];
bool vis[N];
bool find(int u, int n) {
    for (int i = 1; i <= n; ++i) {
        if (f[u][i] && !vis[i]) {
            vis[i] = 1;
            if (!l[i] || find(l[i], n)) {
                l[i] = u;
                return 1;
            }
        }
    }
    return 0;
}
class SafeReturn {
    public:
        int minRisk(int T, vector <string> streets) {
            int n = streets.size();
            memset(d, 63, sizeof(d));
            for (int i = 0; i < n; ++i)
                for (int j = 0; j < n; ++j)
                    if (streets[i][j] != '-')   d[i][j] = streets[i][j] - '0';
            for (int i = 0; i < n; ++i) d[i][i] = 0;
            for (int k = 0; k < n; ++k)
                for (int i = 0; i < n; ++i)
                    for (int j = 0; j < n; ++j)
                        d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            for (int i = 1; i <= T; ++i)
                for (int j = 1; j <= T; ++j)
                    if (i != j && d[0][j] + d[j][i] == d[0][i]) f[i][j] = 1;
            int ans = T;
            for (int i = 1; i <= T; ++i) {
                memset(vis, 0, sizeof(vis));
                if (find(i, T)) --ans;
            }
            return ans;
        }
};