Codeforces Round 374(div2)解题报告

A.One-dimensional Japanese Crossword

encrypt:加密
integer:整数
corresponding:相应的

image

题目大意

给定一个长度为 n(1n100) 的字符串 输出其中连续 'B' 的段数 并且按顺序输出每一段中含 'B' 的数量

Solution

按题意模拟即可 具体操作可以见代码
时间复杂度 O(n)

点击查看代码
/*
开一个ans数组记录答案
为方便统计答案 给第n+1位赋值为W
统计答案的时候 如果s[i]='B' 就一直跳到最远的B并且记录次数 然后把i变成那个位置 
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;

inline int read() {
	int xr = 0, F = 1;
	char cr;
	while (cr = getchar(), cr < '0' || cr > '9') if (cr == '-') F = -1;
	while (cr >= '0' && cr <= '9') 
		xr = (xr << 3) + (xr << 1) + (cr ^ 48), cr = getchar();
	return xr * F;
}

void write(ll x) {
	char ws[51];
	int wt = 0;
	if (x < 0) putchar('-'), x = -x;
	do {
		ws[++wt] = x % 10 + '0';
		x /= 10;
	} while (x);
	for (int i = wt; i; --i) putchar(ws[i]);
}

namespace steven24 {
	
const int N = 521;
char s[N];
int ans[N];
int n, tot;

void main() {
	n = read();
	for (int i = 1; i <= n; ++i) scanf(" %c", &s[i]);
	s[n + 1] = 'W';
	for (int i = 1; i <= n; ++i) {
		if (s[i] == 'B') {
			++tot;
			int cnt = 1;
			while (s[i + 1] == 'B') ++i, ++cnt;
			ans[tot] = cnt;
		}
	}
	write(tot), putchar('\n');
	for (int i = 1; i <= tot; ++i) write(ans[i]), putchar(' ');
}	
	
}

int main() {
	steven24::main();
	return 0;
}

B.Passwords

specify:明确规定
authorize:授权,批准
enter:输入
arbitrary:任意的

题目大意

给定 n(1n100) 个字符串作为可能密码
再给定正确密码
会按字符串长度从小到大的顺序尝试可能密码 长度相同的字符串可按任意顺序尝试 每次尝试密码需要1s
给定一个 k(1k100) 累计 k 次密码错误后会额外罚时5s
问试到正确密码最少要多少秒 最多需要多少秒

Solution

假设密码串的长度为 len 则所有长度小于 len 的串都必须在密码串前被尝试
而最少秒数显然是当尝试所有长度为 len 的密码使第一个尝试正确密码
而最多秒数显然是当尝试所有长度为 len 的密码使所有错误密码都被尝试一遍再试正确密码
所以扫一遍记录长度小于 len 的字符串个数和长度等于 len 且与密码串不同的字符串个数即可
时间复杂度 O(n) (s.length() 复杂度为常数)

点击查看代码
/*
计算长度比它小的字符串数量和长度等于它的字符串数量
假设前面输入了x次 需要的时间就是x+x/k*5 
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;

inline int read() {
	int xr = 0, F = 1;
	char cr;
	while (cr = getchar(), cr < '0' || cr > '9') if (cr == '-') F = -1;
	while (cr >= '0' && cr <= '9') 
		xr = (xr << 3) + (xr << 1) + (cr ^ 48), cr = getchar();
	return xr * F;
}

void write(ll x) {
	char ws[51];
	int wt = 0;
	if (x < 0) putchar('-'), x = -x;
	do {
		ws[++wt] = x % 10 + '0';
		x /= 10;
	} while (x);
	for (int i = wt; i; --i) putchar(ws[i]);
}

namespace steven24 {
	
const int N = 521;
string s[N];
string pass;
int len;
int cnt1, cnt2;
int n, k;	

void main() {
	cin >> n >> k;
	for (int i = 1; i <= n; ++i) cin >> s[i];
	cin >> pass;
	len = pass.length();
	for (int i = 1; i <= n; ++i) {
		if (s[i].length() < len) ++cnt1;
		else if (s[i].length() == len && s[i] != pass) ++cnt2;
	}
	cout << cnt1 + cnt1 / k * 5 + 1 << " ";
	cnt1 += cnt2;
	cout << cnt1 + cnt1 / k * 5 + 1 << "\n"; 
}	
	
}

int main() {
	ios::sync_with_stdio(false);
	steven24::main();
	return 0;
}

C.Journey

encounter:偶然遇到(怎么这词见了第三遍了还不会)

一定要记得算空间啊!!!!MLE炸了一发

题目大意

给定一个 n(2n5000) 个点 m(1m5000) 条边 的 DAG 图 通过每条边需要花费 ti(1ti109) 的时间 给定一个最大用时 T(1 leT109)T 时间内从 1 出发 n 点结束最多能经过多少点 并输出方案

Solution

因为 n 的范围很小 我们可以暴力一点 直接考虑设 fi,j 表示当前在 i 点 一共经过了 j 个点的最短用时
转移的时候枚举 uv 的边 枚举 k[1,n]fv,k=min(fu,k1+t(u,v))
初值 f1,1=0

问题在于转移顺序 实际上我们想要的就是在使用这个状态之前所有能转移到它的状态都已经转移完毕
通过一些手搓不难发现 实际按距离起点最多经过多少边到达排序即可 数据范围很小 用 spfa 也不会被卡

对于方案输出 另开一个 prei,j 来记录 fi,j 的前置状态即可
统计答案时 开个栈不断往前跳并记录即可 具体可以参考下代码

点击查看代码
/*
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;

inline int read() {
	int xr = 0, F = 1;
	char cr;
	while (cr = getchar(), cr < '0' || cr > '9') if (cr == '-') F = -1;
	while (cr >= '0' && cr <= '9') 
		xr = (xr << 3) + (xr << 1) + (cr ^ 48), cr = getchar();
	return xr * F;
}

void write(ll x) {
	char ws[51];
	int wt = 0;
	if (x < 0) putchar('-'), x = -x;
	do {
		ws[++wt] = x % 10 + '0';
		x /= 10;
	} while (x);
	for (int i = wt; i; --i) putchar(ws[i]);
}

bool s1;

namespace steven24 {
		
const int N = 5210;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int f[N][N];
int pre[N][N];
int head[N], to[N], nxt[N], len[N], cnt;
int maxdis[N], xu[N];
bool exist[N];
int stk[N], top;
int n, m, T;

struct node {
	int id, dis;
	friend bool operator<(node x, node y) {
		return x.dis < y.dis;
	}
} a[N];

inline void add_edge(int x, int y, int z) {
	to[++cnt] = y;
	nxt[cnt] = head[x];
	head[x] = cnt;
	len[cnt] = z;
}

queue<int> q;
void spfa() {
	maxdis[1] = 0;
	q.push(1);
	exist[1] = 1;
	while (!q.empty()) {
		int now = q.front();
		q.pop();
		for (int i = head[now]; i; i = nxt[i]) {
			int y = to[i];
			if (maxdis[y] < maxdis[now] + 1) {
				maxdis[y] = maxdis[now] + 1;
				if (!exist[y]) q.push(y), exist[y] = 1;
			}
		}
		exist[now] = 0;
	}
}

void main() {
	n = read(), m = read(), T = read();
	for (int i = 1; i <= m; ++i) {
		int x = read(), y = read(), z = read();
		add_edge(x, y, z);
	}
	
	
	spfa();
	
	for (int i = 1; i <= n; ++i) a[i].id = i, a[i].dis = maxdis[i];
	sort(a + 1, a + 1 + n);
	for (int i = 1; i <= n; ++i) xu[i] = a[i].id;
	
	
	memset(f, 0x3f, sizeof f);
	f[1][1] = 0;
	for (int i = 1; i <= n; ++i) {
		int now = xu[i];
		for (int j = head[now]; j; j = nxt[j]) {
			int y = to[j];
			for (int k = 1; k <= n; ++k) {
				if (f[y][k] > f[now][k - 1] + len[j]) {
					f[y][k] = f[now][k - 1] + len[j];
					pre[y][k] = now;
				}
			}
		}
	}
	
	
	int ans;
	for (int i = 2; i <= n; ++i) {
		if (f[n][i] <= T) ans = i;
	}
	int p = n;
	int cnt = ans;
	stk[++top] = p;
	while (cnt) {
		p = pre[p][cnt];
		stk[++top] = p;
		--cnt;
		if (cnt == 0) break;
	}
	
	write(ans), putchar('\n');
	for (int i = top - 1; i; --i) write(stk[i]), putchar(' ');
}	
	
}

bool s2;

int main() {
	steven24::main();
	cerr << "size = " << (&s1 - &s2) / 1024 / 1024;
	return 0;
}
posted @   Steven24  阅读(556)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示