挂得太惨了,这样下去可不行啊...
String Master
题意并没有看错,但就是不知道为什么第一眼上去就开始写模拟,更蠢的是明明写着写着发现完全能用(n^3)的傻逼DP莽过,但是就是蜜汁自信觉得模拟没问题。
最后一个细节没处理好挂掉50分。
不过可能也跟我考试不喜欢写对拍有关系吧...
以后能写对拍一定要写对拍
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 305;
char s[maxn], t[maxn];
int dp[maxn][maxn][maxn];
int n, kk;
int main() {
freopen("master.in", "r", stdin);
freopen("master.out", "w", stdout);
cin >> n >> kk;
scanf("%s %s", s + 1, t + 1);
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 0; k <= kk; k++) {
if (s[i] == t[j]) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k] + 1);
else if (k) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k - 1] + 1);
ans = max(ans, dp[i][j][k]);
}
}
}
cout << ans << endl;
return 0;
}
Tourist Attractions
做题经验还是太少,完全没想到是容斥去做...而且考场暴力+1写成++不小心改了递归变量里的一个值爆了0
答案就是所有可能的路径数 - 1和3相同的 - 2和4相同的 + 1和3、2和4都相同的 - 三元环 × 6(每个边2次)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <bitset>
using namespace std;
const int maxn = 1505;
char s[maxn][maxn];
long long n, d[maxn], dp[5][maxn];
bitset<maxn> b[maxn];
int main() {
freopen("tourist.in", "r", stdin);
freopen("tourist.out", "w", stdout);
scanf("%lld", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", s[i] + 1);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (s[i][j] == '1')
d[i]++;
}
}
for (int i = 1; i <= n; i++) dp[1][i] = 1;
for (int k = 2; k <= 4; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (s[i][j] == '1' || s[j][i] == '1') dp[k][i] += dp[k - 1][j];
long long ans = 0;
for (int i = 1; i <= n; i++) ans += dp[4][i];
for (int i = 1; i <= n; i++) ans -= d[i] * d[i] * 2;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (s[i][j] == '1') b[i][j] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (s[i][j] == '1') ans++;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (b[i][j])
ans -= (b[i] & b[j]).count() * 2;
cout << ans << endl;
return 0;
}
Walk
普通的边直接用一个BFS去更新(写在主函数里)
注意用子集去更新时只去更新1的个数比当前节点少1的点数即可,这样在BFS时传的边权都应该是一样的。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <deque>
#include <vector>
using namespace std;
const int maxn = 2e5 + 10;
vector<int> num[1048579];
queue<int> q;
int n, m;
int dis[1048577];
int val[maxn];
bool vis[1048577];
struct edge {
int nex, to;
}e[maxn << 2];
int head[maxn], tot;
void Add(int u, int v) {
e[++tot] = (edge) { head[u], v };
head[u] = tot;
}
void BFS(int u, int dep) {
vis[u] = 1;
for (int i = 0; i < num[u].size(); i++) {
int v = num[u][i];
if (dis[v] > dep) {
dis[v] = dep;
q.push(v);
}
}
for (int i = 1; i <= u; i <<= 1) {
if (!(u & i)) continue;
if (!vis[u ^ i]) BFS(u ^ i, dep);
}
}
int main() {
freopen("walk.in", "r", stdin);
freopen("walk.out", "w", stdout);
cin >> n >> m;
int u, v;
for (int i = 1; i <= n; i++) {
scanf("%d", &val[i]);
num[val[i]].push_back(i);
}
for (int i = 1; i <= m; i++) {
scanf("%d %d", &u, &v);
Add(u, v);
}
memset(dis, 0x3f, sizeof dis);
dis[1] = 0;
q.push(1);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; i; i = e[i].nex) {
int v = e[i].to;
if (dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
q.push(v);
}
}
if (!vis[val[u]]) BFS(val[u], dis[u] + 1);
}
for (int i = 1; i <= n; i++) {
if (dis[i] == 0x3f3f3f3f)
printf("-1
");
else
printf("%d
", dis[i]);
}
return 0;
}