周测题解8.23
这个国王的新连麦键就nm尴尬
还有T3正解是暴搜T4是模拟,这里主要说一下T1和T2。
T1
一个树形DP。
设计状态
设
这里就会发现,这其实是一个森林:所有没有先修课的课都是一棵树的根。
那么我们就可以直接让输入的
所以一共要学
初始状态
这个也不难想。从
即
状态转移
一棵树的状态从哪来?当然是从子树来了。下面称
则有状态转移方程:
这里有两个关键:
的范围
首先
然后,
的枚举顺序
这其实类似01背包。
如果
所以要求更新
即大的比小的早更新,
代码
#include <iostream>
#include <list>
using namespace std;
list<int> edge[301];int n, m, dp[301][301];
void dfs(int x)
{
for(auto &v : edge[x])
{
dfs(v);
for(int i = m + 1;i >= 1;--i)
for(int j = 1;j < i;++j)
dp[x][i] = max(dp[x][i], dp[v][j] + dp[x][i - j]);
}
}
int main()
{
cin >> n >> m;
for(int i = 1, v;i <= n;++i)
cin >> v >> dp[i][1], edge[v].push_back(i);
dfs(0);
cout << dp[0][m + 1];
return 0;
}
T2
分层图模板题。
建图
本题唯一难点。
想象一下原图分成上下分离的,平行的若干层。
平行的层中对应点有 0 权边。
每条边在相邻层的对应点上也有 0 权边。
需要算从第一层的
相信大家不难看出,0 权边模拟的是免费机票。
每用一次免费机票,就往下一层。
如果不用就直接到下一层的对应点,也存在 0 权边。
那总共最多用
那这题就没了。
代码
可以用
#include <iostream>
#include <list>
#include <queue>
#include <functional>
#include <utility>
#include <cstring>
using namespace std;
list<pair<int, int> > edge[2000001];int n, m, k, s, t, u, v, w, dis[2000001], vis[2000001];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
void add(int u, int v, int w) {edge[u].push_back(make_pair(w, v));}
int main()
{
cin >> n >> m >> k >> s >> t;
for(int i = 0;i < k;++i)
for(int j = 0;j < n;++j)
add(j + i * n, j + (i + 1) * n, 0);
for(int i = 0;i < m;++i)
{
cin >> u >> v >> w;
for(int j = 0;j < k;++j)
{
add(u + j * n, v + j * n, w);
add(v + j * n, u + j * n, w);
add(u + j * n, v + (j + 1) * n, 0);
add(v + j * n, u + (j + 1) * n, 0);
}
add(u + k * n, v + k * n, w);
add(v + k * n, u + k * n, w);
}
memset(dis, 0x3f, sizeof dis);
q.push(make_pair(0, s));dis[s] = 0;
while(!q.empty())
{
int u = q.top().second;q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(auto &i : edge[u])
if(dis[i.second] > dis[u] + i.first)
{
dis[i.second] = dis[u] + i.first;
q.push(make_pair(dis[i.second], i.second));
}
}
cout << dis[t + k * n];
return 0;
}
T3
暴搜大家应该都会写。
这里就是比一般的遍历图多了个数组,记录游览过的文明。
游览一个点前要判断:
- 这个点没到过
- 这个点的文明没访问过
- 这个点的文明和之前访问的都不冲突
然后就是 dfs 板子了。
这是学长的代码(自己加的注释):
#include<bits/stdc++.h>
#define R register
#define ll long long
#define N 4010
#define p 20000528
#define inf 0x3f3f3f3f
#pragma GCC optimize(3) //手动开O3最好不要学
using namespace std;
inline int read()
{
R int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
void out(R int x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)out(x/10);putchar(x%10+'0');
}
int n,k,m,s,t;
int c[N],a[N][N],head[N],net[N],to[N],tot,w[N];
void add(R int x,R int y,R int z)
{
to[++tot]=y;
w[tot]=z;
net[tot]=head[x];
head[x]=tot;
}
int ans=inf;
int vc[N],v[N],cnt;
void dfs(R int x,R int y,R int stp)
{
if(stp>ans)return; //剪枝,如果现在搜到的比当前答案大,就没必要搜了
if(x==y)ans=min(stp,ans); //到了
for(R int i=head[x];i;i=net[i])
{
int vj=to[i];
int f=0;
for(R int j=1;j<=k;j++)
if(vc[j]&&a[j][c[vj]]) //如果之前访问过的文明和下一个冲突
{
f=1;break;
}
if(!v[vj]&&!vc[c[vj]]&&!f) //三个条件
{
v[vj]=1,vc[c[vj]]=1;
dfs(vj,y,stp+w[i]);
v[vj]=0,vc[c[vj]]=0;
}
}
}
int main()
{
n=read(),k=read(),m=read(),s=read(),t=read();
for(R int i=1;i<=n;i++)c[i]=read();
for(R int i=1;i<=k;i++)
for(R int j=1;j<=k;j++)
a[i][j]=read();
for(R int i=1;i<=m;i++) {
R int x,y,z;
x=read(),y=read(),z=read();
add(x,y,z);
add(y,x,z);
}
v[t]=1,vc[c[t]]=1;
dfs(t,s,0);
out(ans==inf?-1:ans);
return 0;
}
T4
没啥好说的,纯模拟题。
这里只需要注意越界问题就行了(即[减后+n防负数]和[%n防溢出])
#include <iostream>
#include <string>
using namespace std;
struct p
{
bool f;string s;
}a[100001];
int n, m, ans, x, y;
int main()
{
cin >> n >> m;
for(int i = 0;i < n;++i)
cin >> a[i].f >> a[i].s;
for(int i = 0;i < m;++i)
{
cin >> x >> y;
if(!x && !a[ans].f) ans = (ans + n - y) % n;
else if(!x && a[ans].f) ans = (ans + y) % n;
else if(x && !a[ans].f) ans = (ans + y) % n;
else if(x && a[ans].f) ans = (ans + n - y) % n;
}
cout << a[ans].s;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具