12.17 CW 模拟赛 赛时记录
前言
这一次又来更新比赛策略
讲真打了这么久, 还没有一个好的比赛策略真的是抽象
回去吃点感冒药
看题
怎么
思路#
转化题意
对于两组, 一组有
本身就很像
令
考虑转移,
其中
又想了一些杂七杂八的事情, 先放过这个题, 我们看一下
注意以后即使不考试, 也要时间分配好
对于
那么我们将这两个背包组合起来, 就得到了答案
整个的复杂度为
先打, 时间不足后面再来找高分
实现#
框架#
先做两个背包, 然后枚举合并答案即可
代码#
#include <bits/stdc++.h>
#define int long long
const int MAXN = 120;
const int MAXC = 52064;
int n, m;
struct student {
int w; // 能力值
int v; // 精彩度
} stu1[MAXN], stu2[MAXN];
int maxc = 0;
int dp1[MAXC], dp2[MAXC];
/*两边各做一次背包*/
void init()
{
for (int i = 1; i <= 50000; i++) dp1[i] = dp2[i] = -0x3f3f3f3f;
int C = 0; for (int i = 1; i <= n; i++) C += stu1[i].w;
maxc = std::max(maxc, C);
for (int i = 1; i <= n; i++) {
for (int j = C; j >= stu1[i].w; j--) {
dp1[j] = std::max(dp1[j], dp1[j - stu1[i].w] + stu1[i].v);
}
}
C = 0; for (int i = 1; i <= m; i++) C += stu2[i].w;
maxc = std::min(maxc, C);
for (int i = 1; i <= m; i++) {
for (int j = C; j >= stu2[i].w; j--) {
dp2[j] = std::max(dp2[j], dp2[j - stu2[i].w] + stu2[i].v);
}
}
}
signed main()
{
scanf("%lld %lld", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%lld %lld", &stu1[i].w, &stu1[i].v);
for (int i = 1; i <= m; i++)
scanf("%lld %lld", &stu2[i].w, &stu2[i].v);
init();
int Ans = 0;
for (int i = 0; i <= maxc; i++) {
if (dp1[i] != -0x3f3f3f3f && dp2[i] != -0x3f3f3f3f)
Ans = std::max(Ans, dp1[i] + dp2[i]);
}
printf("%lld", Ans);
return 0;
}
预期得分 :
思路#
转化题意,
对于一颗树, 我们定义一个花费是指从
求出对于任意一种
看上去就不好做
先考虑对于确定的
好吧看起来不可做
那么开始骗
对于
对于
不会, 直接不要了
对于链的情况下, 选取中间的点作为集合点一定最优, 那么对于每一个集合点, 我们考虑
算了只要
实现#
框架#
先在外层枚举选择点的情况, 然后进去计算
代码#
#include <bits/stdc++.h>
const int MAXN = 30;
const int MOD = 1e9 + 7;
int n, m;
int Sum = 0;
struct Tree
{
struct node {
int to, next;
} Edge[MAXN << 1];
int head[MAXN], Edge_cnt;
void head_init() { for (int i = 1; i <= n; i++) head[i] = -1; }
void addedge(int u, int v) {
Edge[++Edge_cnt].to = v, Edge[Edge_cnt].next = head[u];
head[u] = Edge_cnt;
}
} tree;
bool tag[MAXN]; // 标记是否有点
int Ans = 0;
int NowAns = 0;
void dfs(int now, int dep, int fa) {
if (tag[now]) (NowAns += dep) %= MOD;
for (int i = tree.head[now]; ~i; i = tree.Edge[i].next) {
int nowto = tree.Edge[i].to;
if (nowto == fa) continue;
dfs(nowto, dep + 1, now);
}
}
void solve(int State)
{
int cnt = 0;
memset(tag, false, sizeof(tag));
while (State) {
if (State & 1) tag[++cnt] = true;
else tag[++cnt] = false;
State >>= 1;
}
Ans = 0x3f3f3f3f, NowAns = 0;
/*外层枚举集合点*/
for (int i = 1; i <= n; i++) {
NowAns = 0;
dfs(i, 0, -1);
Ans = std::min(Ans, NowAns);
}
}
int main()
{
scanf("%d %d", &n, &m);
tree.head_init();
for (int i = 1; i < n; i++) {
int read; scanf("%d", &read);
tree.addedge(i + 1, read), tree.addedge(read, i + 1);
}
/*外层枚举点的情况*/
for (int State = 0; State < (1 << n); State++) {
if (std::__popcount(State) != m) continue;
solve(State);
(Sum += Ans) %= MOD;
}
printf("%d", Sum);
return 0;
}
粗略看一下部分分很足
直接开始, 很显然的我们可以
然后我们就可以计算此时的答案, 这个的复杂度是
但我时间可能不够了, 模拟题你是坠棒的
所以简单的考虑一下
总结
怎么会有
这我骗鸡毛啊
留了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】