2024.11.01模拟赛( — _ — )
唉 不——开——心——
有些话就不说了。T1打假了,打了T3、T4的特殊样例(共10分),原本是抱着爆0的心态的,结果没想到T1数据水到直接给了我70分——但T3T4爆掉了, 总分70分 。差点爆0,不——开————心——————
T1【二分图匹配】
题目大意:
给出两个长度分别为翻译一通后: 求
解题思路:
现在来看,这是
我们会想到设
那么开始dp。设状态
最后,若
70’究竟是打假的正解还是运气好的骗分?
交程序的时候,我完全就是抱着爆0的心态去交的。在调试时,我给自己出了一组数据:忘了,和忘了。
根据我原本定义的dp状态:dp[i]表示当s1串匹配到第i位时,最优的LCS长度与s2串匹配到的位置。
但这样会出现一个问题:比如说在以上数据中,当i=5时,最优的长度为5、但s2串匹配到了最后一位;
当i=?时,按理来说它应通过i=5不那么优的一个方案转移而来,但因为我的dp数组少了一维状态而并不是最优的方案。
但神奇的是,交上去的了70。当时很多人都想知道我是怎么在自己出的数据和大数据都没过的情况下骗到这么多分的,
但那时我也说不清楚,以为是纯纯数据水才让我的错误代码骗到了分。
现在想来,我的dp与正解的dp类似,但相比少了一维长度状态,所以有时就无法取到最优解;而其他的转移也类似,
比如正解中的nxt数组和我程序中的box实现的功能相同。
所以,我的70分并不是的单纯的数据水。我看似全错的dp转移也只是比正解少了一维状态。哎,又是与正解擦肩而过的一次。
可达性dp 神奇的小东西
一大坨代码
#incIude <bits/stdc++.h>
using namespace std;
const int N=2e3+10;
const int M=1e6+5;
int n,m;
int a[M],b[M],box[100];
int f[N][N];//f[i][j]:匹配i个、s1匹配到下标j,s2所匹配到的地方
int nxt[M][30];//nxt[i][j]:b[i]后第一个值为j的位置
string s1,s2;
int ans;
void init()
{
memset(box,0x3f,sizeof box);
memset(nxt,0x3f,sizeof nxt);
}
int main()
{
init();
cin>>n>>m>>s1>>s2;
for (int i=0;i<n;i++) a[i+1]=(int)(s1[i]-'A');
for (int i=0;i<m;i++) b[i+1]=(int)(s2[i]-'A');
for (int i=m;i>=0;i--)//倒序枚举,box记录上一个j值所出现的位置
{
for (int j=0;j<=25;j++)
{
nxt[i][j]=box[j];
if (b[i]==j) box[j]=i;
}
}
for (int i=1;i<=n;i++) f[i][0]=m+1;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
f[i][j]=min(f[i][j-1],nxt[f[i-1][j-1]][a[j]]);//不匹配第j个,与匹配第j个
}
}
for (int i=n;i>=1;i--)
{
if (f[i][n]<=m)//没有跳出去 即可行
{
cout<<i;
break;
}
}
return 0;
}
T2【虚图】
题目大意:
给出由n个节点、m条边组成的无向图
解题思路:
这题乍一看,是道既不能n下单源最短路、也不能多源最短路的神奇题目。但是我们想到,伟大的dijstra算法复杂度为
但是众所周知,dij是单源最短路;又但是,我们注意到,在该题目中只有关键点有用,那么我们或许会想起双向搜索——走向终点的同时,终点也在走向我,那么,这道题可不可以也用类似的东西捏……
于是乎!我们联想到了把所有的“起点”与“终点”放进小根堆中,也就放进所有的关键点,让它们一起跑dijstra。接着,我们就神奇地发现:没问题了!对于一个点,若它被两个关键点的路径松弛过,那么它一定会是一个答案(因为是dij,它一定会是优的)。但是!我们要注意一下,“两个关键点”,这很重要,每个
于是乎,我们把所有的关键点放入大根堆,然后跑一遍普通的dij就好了。但是,我们怎么才能记录答案呢?毕竟对于一个点,我们只记录了一条从某点到它的最小路。我们可以想到,一条边一定连着两个点u,v,若是
如果大山不会走向穆罕默德,穆罕默德可以走向大山。
两大坨代码
#incIude <bits/stdc++.h>
#define pii pair<int,int>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m,T;
struct node { int nxt,val; };
vector <node> e[N];
struct node2 { int uu,vv,ww; } b[N];
int p[N];
int ans=0x3f3f3f3f3f3f3f3f;
int dis[N],c[N];
bool vis[N];
priority_queue < pii,vector <pii>,greater<pii> > q;
void read()
{
scanf("%lld%lld%lld",&n,&m,&T);
for (int i=1;i<=m;i++)
{
int u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
e[u].push_back({v,w});
e[v].push_back({u,w});
b[i]={u,v,w};//记录下边
}
for (int i=1;i<=T;i++) scanf("%lld",&p[i]);
}
void dijstra()
{
memset(dis,0x3f,sizeof dis);
for (int i=1;i<=T;i++)
{
q.push(make_pair(0,p[i]));
dis[p[i]]=0;
c[p[i]]=p[i];//记录是从哪个关键点到的
}
while (!q.empty())
{
pii t=q.top();
q.pop();
int u=t.second;
if (vis[u]) continue;
vis[u]=true;
for (int i=0;i<e[u].size();i++)
{
int v=e[u][i].nxt,w=e[u][i].val;
if (dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
c[v]=c[u];
q.push(make_pair(dis[v],v));
}
}
}
}
signed main()
{
read();
dijstra();
for (int i=1;i<=m;i++)
{
int u=b[i].uu,v=b[i].vv,w=b[i].ww;
if (c[u]==0||c[v]==0) continue;
if (c[u]!=c[v]) ans=min(ans,dis[u]+dis[v]+w);//若是出现u->v->u的情况,那么不要取
}
printf("%lld",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】