2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(省赛)
·
T1
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
int w[N];
int main()
{
int n, cur;
scanf("%d%d", &n, &cur);
for(int i = 1; i <= n; i++)
scanf("%d", &w[i]);
int ans1 = 0, ans2 = 0;
for(int i = 1; i <= n; i++, cur++)
{
if(cur > 7) cur = 1;
if(w[i] >= 35 && cur != 4) ans1++;
if(w[i] >= 35 && cur == 4) ans2++;
}
printf("%d %d", ans1, ans2);
}
T2
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
int w[N] = {0, 12, 9, 7, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1};
int ans[22];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
for(int i = 1; i <= 20; i++)
{
int p, k;
scanf("%d%d", &p, &k);
ans[i] += w[p] + k;
}
}
for(int i = 1; i <= 20; i++)
printf("%d %d\n", i, ans[i]);
}
T3
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int g[N][N], w[N][N];
int n, m;
void f(int a, int b, int x)
{
bool nom = true;
for(int i = a-1; i <= a+1; i++)
for(int j = b-1; j <= b+1; j++)
{
if(i < 1 || j < 1 || i > n || j > m) continue;
if(g[i][j] == 'm') nom = false;
if(w[i][j] == 3 || w[i][j] == 2) continue;
if(x == 1 && w[i][j] == 4) continue;
w[i][j] = x;
}
if(nom && x == 1)
{
for(int i = a-1; i <= a+1; i++)
for(int j = b-1; j <= b+1; j++)
{
if(i < 1 || j < 1 || i > n || j > m) continue;
if(w[i][j] == 1) w[i][j] = 4;
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
scanf(" %c", &g[i][j]);
if(g[i][j] != '.') w[i][j] = 3; //0空,1可能,2不可能,3被占, 4疑似
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
if(g[i][j] == 'w') f(i, j, 1);
else if(g[i][j] == 'c') f(i, j, 2);
}
bool has = false;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(w[i][j] == 4)
printf("%d %d\n", i, j), has = true;
if(!has) puts("Too cold!");
}
T4
错解
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int M = 2e5 + 10;
int h[N], e[M], ne[M], idx;
int p[N], cnt[N];
int st, ed;
int dist[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int bfs()
{
memset(dist, 0, sizeof dist);
dist[st] = 1;
queue<int> q;
q.push(st);
while (q.size())
{
int u = q.front();
q.pop();
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (u == st && j == ed)
continue;
if (dist[j])
continue;
dist[j] = dist[u] + 1;
if (j == ed)
return dist[j];
q.push(j);
}
}
return -1;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
idx = 0;
memset(h, -1, sizeof h);
memset(cnt, 0, sizeof cnt);
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
p[i] = i;
for (int i = 1; i <= m; i++)
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
int pa = find(a), pb = find(b);
if (pa != pb)
{
cnt[pa] += cnt[pb]; // 归拢环数目到新的根节点
p[pb] = pa;
}
else
{
cnt[pa]++; // 检测到环
st = a, ed = b; // 记录成环的端点
}
}
int s = 0; // 子图个数(注意这个不是环的个数,而是只有一个环的连通块的个数)
for (int i = 1; i <= n; i++)
if (p[i] == i && cnt[i] == 1) // 并查集中一个根节点代表一个连通块
s++;
if (s != 1)
printf("No %d\n", s);
else
printf("Yes %d\n", bfs());
}
}
这个借鉴别人的,有误。这个想通过保留环上间距为1的点对来直接求环的长度,这有问题,因为即便只有一个章鱼子环,但是整个图可能有多个环出现(其它的连通块有多个环,不影响最后的答案),这样保留的st ed甚至可能不在目标环上!!所以还是老实的用topsort把非环点逐个剥离掉,间接算环的大小吧~
正确答案1
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int M = 2 * N;
int h[N], e[M], ne[M], idx;
int p[N], cnt[N], sz[N], d[N];
int n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
void merge(int a, int b)
{
int pa = find(a);
int pb = find(b);
if(pa != pb)
{
p[pa] = pb;
cnt[pb] += cnt[pa];
sz[pb] += sz[pa];
}
else cnt[pb]++;
}
int toposort()
{
int ret = 0;
queue<int> q;
int rt;
for(int i = 1; i <= n; i++)
if(p[i] == i && cnt[i] == 1)
rt = i;
for(int i = 1; i <= n; i++)
{
if(find(i) == rt && d[i] == 1) q.push(i);//必须保证进行topsort的点都来自章鱼图(通过根节点的ez,sz属性来判断)
}
while(q.size())
{
int u = q.front(); q.pop(); ret++;
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(--d[j] == 1) q.push(j);
}
}
return sz[rt] - ret; //这里当然所有点不是n拉,我们是在章鱼图(块)上进行拆环,所有点是sz[rt]
}
int main()
{
int t;
cin >> t;
while(t--)
{
memset(h, -1, sizeof h);
idx = 0;
cin >> n >> m;
for(int i = 1; i <= n; i++) p[i] = i, cnt[i] = 0, d[i] = 0, sz[i] = 1;
for(int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
merge(a, b);
add(a, b);
add(b, a);
d[a]++;
d[b]++;
}
int s = 0;
for(int i = 1; i <= n; i++)
{
if(p[i] == i && cnt[i] == 1)
s++;
}
if(s == 1) printf("Yes %d\n", toposort());
else printf("No %d\n", s);
}
}
正确答案2
下面的用sz ez来判断连通块中环的数量
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int M = 2 * N;
int h[N], e[M], ne[M], idx;
int p[N], cnt[N], sz[N], d[N];
int n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
void merge(int a, int b)
{
int pa = find(a);
int pb = find(b);
if(pa != pb)
{
p[pa] = pb;
cnt[pb] += cnt[pa];
sz[pb] += sz[pa];
}
else cnt[pb]++;
}
int toposort()
{
int ret = 0;
queue<int> q;
int rt;
for(int i = 1; i <= n; i++)
if(p[i] == i && cnt[i] == 1)
rt = i;
for(int i = 1; i <= n; i++)
{
if(find(i) == rt && d[i] == 1) q.push(i);//必须保证进行topsort的点都来自章鱼图(通过根节点的ez,sz属性来判断)
}
while(q.size())
{
int u = q.front(); q.pop(); ret++;
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(--d[j] == 1) q.push(j);
}
}
return sz[rt] - ret; //这里当然所有点不是n拉,我们是在章鱼图(块)上进行拆环,所有点是sz[rt]
}
int main()
{
int t;
cin >> t;
while(t--)
{
memset(h, -1, sizeof h);
idx = 0;
cin >> n >> m;
for(int i = 1; i <= n; i++) p[i] = i, cnt[i] = 0, d[i] = 0, sz[i] = 1;
for(int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
merge(a, b);
add(a, b);
add(b, a);
d[a]++;
d[b]++;
}
int s = 0;
for(int i = 1; i <= n; i++)
{
if(p[i] == i && cnt[i] == 1)
s++;
}
if(s == 1) printf("Yes %d\n", toposort());
else printf("No %d\n", s);
}
}
T5
#include <bits/stdc++.h>
using namespace std;
const int N = 5010;
int f[N];
struct node
{
int t, d, p;
bool operator<(const node &u) const
{
if (d != u.d)
return d < u.d;
return t > u.t;
}
} a[N];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
memset(f, 0, sizeof f);
int tm = 0;
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d%d", &a[i].t, &a[i].d, &a[i].p), tm = max(tm, a[i].d);
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++)
for (int j = a[i].d; j >= a[i].t; j--)
f[j] = max(f[j], f[j-a[i].t]+a[i].p);
int ans = 0;
for(int i = 1; i <= tm; i++)
ans = max(ans, f[i]);
printf("%d\n", ans);
}
}
一般背包问题只有下限,这里还有上限。更新区间在下限~上限。
因此最优状态并不一定在Vm。
所以需要遍历所有状态。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)