「CSP模拟」模拟测试6

挂得太惨了,这样下去可不行啊...

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\n");
	else 
	    printf("%d\n", dis[i]);
    }
    return 0;
}
posted @ 2020-09-24 19:54  zfio  阅读(130)  评论(1编辑  收藏  举报