首页 > 其他分享 >ABC375 Review

ABC375 Review

时间:2024-10-14 09:46:57浏览次数:9  
标签:dp1 min int Review vector ABC375 void dp

ABC375 Review

A B

模拟题 过

C

很让人恼怒的一道题,思路一点也不难想,但是代码实现过于困难了(对于我来说)

分析

自己找一两组样例就会发现这道题实际上实在模拟一个矩阵不断向内旋转 \(90°\) 的过程,从外到里旋转的次数越来越多,旋转的过程可以发现实际上可以通过模 \(4\) 来进行简化,然后只需做一个坐标的映射就可以了,难度完全在于代码实现上面。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=3010;
char mp[N][N],ans[N][N];
int n;
inline void pre()
{
	cin>>n;
	for(int i=1;i<=n;++i)
	{
		getchar();
		for(int j=1;j<=n;++j)mp[i][j]=getchar(),ans[i][j]=mp[i][j];
	}
}
inline void debug()
{	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=n;++j)putchar(ans[i][j]);
		putchar('\n');
	}
	
}
inline void getans(int x)
{
	
	int y=n-x+1;
	int times=x%4;
		if(times==0)
			{
				for(int j=x;j<=y;++j)ans[x][j]=mp[x][j],ans[y][j]=mp[y][j];
				for(int i=x+1;i<=y-1;++i)ans[i][x]=mp[i][x],ans[i][y]=mp[i][y];
			}
		else if(times==1)
			{
				for(int j=x;j<=y;++j)ans[x][j]=mp[n-j+1][x],ans[y][j]=mp[n-j+1][y];
				for(int i=x+1;i<=y-1;++i)ans[i][x]=mp[y][i],ans[i][y]=mp[x][i];
			}
		else if(times==2)
			{
				for(int j=x;j<=y;++j)ans[x][j]=mp[y][n-j+1],ans[y][j]=mp[x][n-j+1];
				for(int i=x+1;i<=y-1;++i)ans[i][x]=mp[n-i+1][y],ans[i][y]=mp[n-i+1][x];
			}
		else if(times==3)
			{
				for(int j=x;j<=y;++j)ans[x][j]=mp[j][y],ans[y][j]=mp[j][x];
				for(int i=x+1;i<=y-1;++i)ans[i][x]=mp[x][n-i+1],ans[i][y]=mp[y][n-i+1];
			}
//	putchar('\n');
//	debug();
}
inline void solve()
{
	for(int i=1;i<=n/2;++i)getans(i);
	debug();
}
int main()
{
	pre();
	solve();
	return 0;
 } 

D

在 \(S\) 里找到长度为 \(3\) 的回文串的数量

分析

由于长度只有 \(3\) ,所以可以直接枚举中间的那个字母,然后找两边一样的即可,产生的答案是两边相同字母数量分别乘积然后再求和。

小坑点

这个会爆 int ,一开始想到了,但是写的时候还是 wa 了一发,实际上直接 define 或许会更加方便一点。

Code

#include<bits/stdc++.h>
using namespace std;
string s;
long long ans;
const int N=2e5+10;
int l[N][30],r[N][30];
inline void pre()
{
	cin>>s;
	for(int i=1;i<s.length();++i)
	{
		for(int j=0;j<26;++j)
		{
			l[i][j]=l[i-1][j];
			if(s[i-1]==j+'A')l[i][j]++;	
		}	
	}
	for(int i=s.length()-2;i>=0;--i)
	{
		for(int j=0;j<26;++j)
		{
			r[i][j]=r[i+1][j];
			if(s[i+1]==j+'A')r[i][j]++;	
		}		
	}		
}
inline void solve()
{
	for(int pos=1;pos<s.length()-1;++pos)
		for(int i=0;i<26;++i)
			ans+=1ll*l[pos][i]*r[pos][i];
	cout<<ans;
}
int main()
{
	pre();
	solve();
	return 0;
 } 

E

每个人初始属于三个集合中的某一个,且带有一个初始价值,求一个最小的移动数量,使得三个集合的总价值相同,(如果有的话)。

分析

现在算是总结出来一个规律,只要是没什么清晰思路的题目,十有八九是个dp。

这个数据范围那肯定爆搜是会G的,看这种集合划分问题,一般可能就是dp了。

仔细想想,后面的人怎么选,也不会影响前面的选择,只是需要一个阶段和三个状态,以为一定会 T,所以没有去写(实际上说时间也是不够了)。

implementation

当任何一个阶段 \(i\) 完成之后,如果 前两个集合的价值是确定的,那么一定有一个唯一的 第三个集合的价值 与之对应, 那么你只需要从 \(1-n\) 枚举每一个人,然后讨论把他丢到哪一个集合即可,

收获

发现日本人十分喜欢使用vector

vector 可以快速赋值,定长度vector和数组基本上没有什么区别

vector 可以快速复制,函数是 newvec=move(vec);

Code

#include<bits/stdc++.h>
using namespace std;
const int N=1000,inf=1e9+7;
int n,s,tar,a[N],b[N];
inline void pre()
{
	cin>>n;
	for(register int i=1;i<=n;++i)
	{
		cin>>a[i]>>b[i];
		s+=b[i];
	}
}
inline void solve()
{
	if(s%3)
	{cout<<"-1";return ;}
	tar=s/3;
	vector<vector<int>> dp(tar+10,vector<int>(tar+10,inf));
	dp[0][0]=0;
	for(int i=1;i<=n;++i)
	{
		int w=b[i];
		vector<vector<int>> dp1(tar+10,vector<int>(tar+10,inf));
		for(int j=0;j<=tar;++j)
		{
			for(int k=0;k<=tar;++k)
			{
				if(a[i]==1)
				{
					if(j-w>=0)dp1[j][k]=min(dp1[j][k],dp[j-w][k]);
					if(k-w>=0)dp1[j][k]=min(dp1[j][k],dp[j][k-w]+1);
					dp1[j][k]=min(dp1[j][k],dp[j][k]+1);					
				}
				else if(a[i]==2)
				{
					if(j-w>=0)dp1[j][k]=min(dp1[j][k],dp[j-w][k]+1);
					if(k-w>=0)dp1[j][k]=min(dp1[j][k],dp[j][k-w]);
					dp1[j][k]=min(dp1[j][k],dp[j][k]+1);
				}
				else
				{
					if(j-w>=0)dp1[j][k]=min(dp1[j][k],dp[j-w][k]+1);
					if(k-w>=0)dp1[j][k]=min(dp1[j][k],dp[j][k-w]+1);
					dp1[j][k]=min(dp1[j][k],dp[j][k]);	
				}
			}
		}
		dp=move(dp1);
	}
	cout<<(dp[tar][tar]==inf?-1:dp[tar][tar]);
}
int main()
{
	pre();
	solve();
	return 0;
}

F

看起来像是一个最短路,于是写了一个超级暴力。。。。

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void re(T &x)
{
	x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f;
}
template<typename T>inline void wr(T x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)wr(x/10);
	putchar(x%10^48);
}
const int N=500,M=3e5+1;
const int INF=2005120700;
struct Edge
{
	int v,nex,w;
}E[M];
int tote,head[N];
inline void add(int u,int v,int w)
{
	E[++tote].v=v,E[tote].w=w,E[tote].nex=head[u];
	head[u]=tote;
}
bool blocked[M];
int n,m,q,u,v,w;
inline void dijkstra(int s,int t)
{
	vector<int> vis(n+1,0);
	vector<int> dis(n+1,INF);
	priority_queue< pair<int,int> > q;
	q.push(make_pair(0,s)),dis[s]=0;
	while(q.size())
	{
		int x=q.top().second;
		q.pop();
		if(vis[x])continue;
		for(int i=head[x];i;i=E[i].nex)
		{
			if(blocked[i])continue;
			int v=E[i].v;
			if(dis[x]+E[i].w>dis[v])continue;
			dis[v]=E[i].w+dis[x];
			q.push(make_pair(-dis[v],v));
		}
		vis[x]=1;
	}
	int res=dis[t];
	wr(res==INF?-1:res),putchar('\n');
}
inline void solve()
{
	re(n),re(m),re(q);
	for(register int i=1;i<=m;++i)
	{
		re(u),re(v),re(w);
		add(u,v,w);
		add(v,u,w);
	}
	int opt;
	while(q--)
	{
		re(opt);
		if(opt==1)
		{
			re(u);
			blocked[2*u]=blocked[2*u-1]=1;	
		}
		else
		{
			re(u),re(v);
			dijkstra(u,v);
		}
	}
}
int main()
{
	solve();
	return 0;
} 

标签:dp1,min,int,Review,vector,ABC375,void,dp
From: https://www.cnblogs.com/Hanggoash/p/18463466

相关文章

  • 24/10/13 ABC375补题笔记
    A典,属于显而易见的水题,这数据范围直接暴力做就行了。#include<bits/stdc++.h>usingnamespacestd;intmain(){ intn; cin>>n; strings; cin>>s; intcnt=0; if(n<2)returncout<<0<<endl,0; for(inti=0;i<s.size()-2;i++)......
  • ABC375 (A~G) 题解
    也是补完整场了。(虽然只有一题要补A模拟。B模拟。C模拟。D模拟。EE-3TeamDivision还想了蛮久的。题意:有三个队伍,各有一些人,人有能力值,人可以换队伍。问三个队伍能力值相同最少需要让多少人交换队伍。人数\(\le100\),值域\(\le1500\)题目还是挺误导人的,如......
  • ABC375
    前言F、G没时间写了,主要是C太唐了,甚至没想到转两遍的只需要把转一遍的循环两边就行了,浪费太多时间,D因为C++20特殊性质CE了一发,E数组开小吃了一发罚时。A、B没啥好说的从C开始吧。C-SpiralRotation发现就是从歪往里数第多少层就是顺时针转多少圈,由此\(\mod4\)......
  • Code Review:探索工程实践之道
    作者:京东物流冯志文前言本文参考《京东JAVA代码规范-V1.1》&Google代码评审工程实践方法论,结合团队代码评审的实践经验整理成文档,这份文档是我们团队集体经验的结晶。我相信公司其他部门也有类似的经验和最佳实践。希望通过互相交流和学习,共同提高代码质量,进而提高系统的稳定......
  • CF 977 Review
    CF977Review掉大分了,我去,绿名也是可以掉分的,我去你简直太牛了sgh。我是真正的飞舞。A排序以后贪心或者直接优先队列模拟即可,都可以过。Code#include<bits/stdc++.h>usingnamespacestd;template<typenameT>inlinevoidre(T&x){ x=0;intf=1;charc=getchar(); wh......
  • CF974 Review
    CF974Review(以后比较简单的题就不写了)ABCskipD个人写了\(O(n\logn)\)的类模拟算法,能过,但不能做到$O(n)$。考虑什么时候一段\([st,st+d-1]\)的时间会和某一段区间有重合,也就是我自己写的算法的核心思想其实。那就是$st+d-1\gel_i\quadst\ler_i$,变形一......
  • ABC372 Review
    ABC372ReviewA语言基础题B类似于二进制拆分,就像跳LCA的时候一样,尽可能多地选大的即可。C一个位置的字母被改变仅仅会对相邻两个位置之类的答案产生影响,暴力统计即可。D对于每一个\(i\)去暴力地统计\(j\)显然是不可行的,所以可以转而想一想每个\(j\)会对答案产生多......
  • AI应用的代码审查CodeReview
    AI应用的代码审查CodeReview提示词AsaDeveloper,IwanttoaskyoutoperformaGitHubMergeRequestreview.https://github.com/megadotnet/Springboot-chatapp/commit/3f7c3e2cb919c3d971d10c301da2357d635d7302Considerpreviouscommentsnotedbelowandavoidrepeati......
  • ABC371 Review
    ABC371ReviewA分类讨论题,过B模拟题,过C题意给出一张原始图\(G\),和一张待修改图\(H\),每次对\(H\)进行一次操作可以花费相应的代价删除已经存在的一条边或者是添加未存在的边。问使得两张图同构的最小代价\(W\)是多少。思路以为是什么高级的算法,但是又放在了C......
  • VS2022 17.12.0 Preview2版本对Copilot的功能增强
    前提条件,使用最新版的17.12.0Preview2,并且有有效的CopilotAI订阅,那么可以体验这些新鲜好用的功能增强了CopilotAI对IEnumerableVisualizer的可编辑表达式功能我们可以通过AI实现一些复杂的条件筛查,并且可以即时验证结果是否符合预期,对于开发和调试提供了极大的便利性......