欢迎点此阅读QvQ
250
Description
有两个集合,每个集合有
N(N<50)
个锥面(表示为高
H
和底面半径
* (1): Ha / Ra > Hb / Rb
* (2): Ra < Rb
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 g[N][N], l[N], vis[N];
bool can(int u, int m) {
for (int i = 0; i < m; ++i) {
if (g[u][i] && !vis[i]) {
vis[i] = 1;
if (l[i] == -1 || can(l[i], m)) {
l[i] = u;
return 1;
}
}
}
return 0;
}
struct PointyWizardHats {
int getNumHats(vector <int> th, vector <int> tr, vector <int> bh, vector <int> br) {
int n = th.size(), m = bh.size();
memset(l, -1, sizeof(l));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j) {
if (th[i] * br[j] > tr[i] * bh[j] && tr[i] < br[j]) g[i][j] = 1;
}
int ans = 0;
for (int i = 0; i < n; ++i) {
memset(vis, 0, sizeof(vis));
if (can(i, m)) ++ans;
}
return ans;
}
};
600
Description
A
和
排列后必须满足如下条件:
* (1): 每个格子必须有最多一枚硬币,小
B
选的格子可以没有硬币
* (2): 每一行,每一列,
B
想获得尽量多的权值,
Solution
观察到,如果
B
能获得
考虑到
* (1):没选择这个格子
* (2): 选择了这个格子,下面没有硬币
* (3): 选择了这个格子,下面有硬币
容易想到三进制压缩,考虑状压dp,用三进制状态表示,用记忆化搜索比较容易实现。枚举当前选择的格子,枚举两种有无硬币的情况即可。
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;
vector<pii> g;
const int N = 13, inf = 100;
struct MagicalHats {
int p[N], r[N], c[N], dp[1594323];
int n, m, totcoin, tothat, num;
inline int gao(int mask, int i, int s) {// 0:not selected 1:no coin 2:has coin
return mask + s * p[i];
}
inline int get(int mask, int i) {
return (mask / p[i]) % 3;
}
int dfs(int mask, int cocnt, int hatcnt, int r[], int c[]) {
if (~dp[mask]) return dp[mask];
int &t = dp[mask];
t = -inf;
if (hatcnt == tothat) {
if (cocnt != totcoin) return t = -inf;
for (int i = 0; i < n; ++i)
if (r[i] & 1) return t = -inf;
for (int i = 0; i < m; ++i)
if (c[i] & 1) return t = -inf;
return t = 0;
}
for (int i = 0; i < tothat; ++i) {
int x = g[i].F, y = g[i].S;
int s = get(mask, i);
if (!s) {//not selected
int t1 = -inf, t2 = -inf, state;
if (cocnt < totcoin) {//has coin
int cnt = 1;
if (hatcnt >= num) cnt = 0;
state = gao(mask, i, 2);
r[x] += 2;
c[y] += 2;
t1 = dfs(state, cocnt + 1, hatcnt + 1, r, c) + cnt;
r[x] -= 2;
c[y] -= 2;
}
//no coin
++r[x];
++c[y];
state = gao(mask, i, 1);
t2 = dfs(state, cocnt, hatcnt + 1, r, c);
--r[x];
--c[y];
if (t1 < 0) t = max(t, t2);
if (t2 < 0) t = max(t, t1);
t = max(t, min(t1, t2));
}
}
return t;
}
int findMaximumReward(vector <string> board, vector <int> coins, int numGuesses) {
p[0] = 1;
for (int i = 1; i < 13; ++i) p[i] = p[i - 1] * 3;
this -> n = board.size(), this -> m = board[0].size();
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
if (board[i][j] == 'H') g.pb(mp(i, j));
this -> totcoin = coins.size(), this -> tothat = g.size(), this -> num = numGuesses;
memset(dp, -1, sizeof(dp));
int cnt = dfs(0, 0, 0, r, c);
sort(coins.begin(), coins.end());
if (cnt < 0) return -1;
int ans = 0;
for (int i = 0; i < cnt; ++i) ans += coins[i];
return ans;
}
};