T1:
problem:
有n个节点,要求构造一棵树,第i个节点的权值为score[degree[i]],degree[i]是节点i的度数。整个树的权值为所有节点权值之和。问树的权值最大为多少。
solution:
显然节点标号是无所谓的,所以就树定向,父亲节点标号小于儿子节点。设fij代表前i - 1个节点处理完了,后面还有j个节点没有父亲。每次枚举当前节点有多少儿子即可转移。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int f[100][100];
class P8XGraphBuilder {
public:
int solve(vector <int> scores) {
int n = scores.size() + 1;
memset(f, -1, sizeof(f));
f[1][n - 1] = 0;
for (int i = 1; i <= n; ++i)
for (int j = 0; j <= n - i; ++j)
if (~f[i][j]) {
f[i + 1][j] = max(f[i + 1][j], f[i][j] + (i != 1 ? scores[0] : 0));
for (int k = 1; k <= j; ++k)
f[i + 1][j - k] = max(f[i + 1][j - k], f[i][j] + scores[k - (i == 1)]);
}
return f[n + 1][0];
}
};
T2:
problem:
给定一个带有'?','1','0'的大小为n * m 的矩阵, 再给 m 个长度为 n 的带有'0' '1' '?'的列('?'代表0,1都有可能)。现在要确定矩阵的所有问号,使得m个列的某种排列能和矩阵的所有列对应起来,输出字典序最小的方案。
solution:
如果不要求字典序最小的话,直接二分图匹配即可。要求字典序最小的话,则只要依次枚举每个问号,尝试放0,那么就会删除一些边。如果删完边还能匹配,那么就换成新图(该位置能放0),否则就保留原图(该位置必须放1)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cassert>
using namespace std;
bool graph[33][33];
bool f[33][33], vis[33];
int my[33], mt[33];
bool find(int x, int n) {
for (int i = 0; i < n; ++i)
if (!vis[i] && f[x][i]) {
vis[i] = true;
if (my[i] == -1 || find(my[i], n)) {
my[i] = x;
return true;
}
}
return false;
}
bool check(int n) {
memset(my, -1, sizeof(my));
int ans = 0;
for (int i = 0; i < n; ++i) {
memset(vis, false, sizeof(vis));
if (find(i, n)) ++ans;
}
if (ans == n) return true;
return false;
}
class P8XMatrixRecovery {
public:
vector <string> solve(vector <string> rows, vector <string> columns) {
int R = rows.size(), C = rows[0].size();
memset(graph, false, sizeof(graph));
for (int i = 0; i < C; ++i)
for (int j = 0; j < C; ++j) {
int k;
for (k = 0; k < R; ++k)
if (rows[k][i] != columns[j][k] &&
rows[k][i] != '?' && columns[j][k] != '?')
break;
if (k >= R) graph[i][j] = true;
}
for (int x = 0; x < R; ++x)
for (int y = 0; y < C; ++y)
if (rows[x][y] == '?') {
memcpy(f, graph, sizeof(f));
memset(f[y], false, sizeof(f[y]));
for (int i = 0; i < C; ++i)
if (graph[y][i] && columns[i][x] != '1')
f[y][i] = true;
if (check(C))
memcpy(graph, f, sizeof(graph));
}
memcpy(f, graph, sizeof(f));
assert(check(C));
for (int i = 0; i < C; ++i)
mt[my[i]] = i;
for (int i = 0; i < R; ++i)
for (int j = 0; j < C; ++j)
if (rows[i][j] == '?') {
if (columns[mt[j]][i] == '?')
rows[i][j] = '0';
else rows[i][j] = columns[mt[j]][i];
}
return rows;
}
};