寒假欢乐赛(一)&&天梯赛(一)补题

文章讲述了作者在寒假编程集训中遇到的C、D、E三道题目,涉及深度优先搜索、二分查找优化、动态规划等技巧,重点在于如何解决C题的背包问题和D题的跳跃问题,以及E题的错误修复和动态规划状态转移的理解。
摘要由CSDN通过智能技术生成

寒假集训欢乐赛1

C题 选数

一开始想写dfs,可是。。可是一直TLE wwwww

后来看了orz代码,思路是:

先暴力 a [i]+a [j],再用二分找 a [mid],代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int n,m;
int a[N];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	sort(a+1,a+1+n);
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			int l=j+1,r=n;
			if(l>n)
			break;
			while(l<=r)
			{	
				int mid=(l+r)>>1;
				if(a[i]+a[j]+a[mid]>m)
				r=mid-1;
				else
				{
					l=mid+1;
					ans=max(ans,a[i]+a[j]+a[mid]);
				}
			}
		}
	}
	cout<<ans;
	return 0;
}

 D题 跳一跳

这题。一开始也是写的dfs |_|

果不其然TLE

其实,i从n点开始往前遍历,从i点向后跳,跳到哪个点就将能到达的点的b数组对应的值加入i点对应的值,表示多了b[i+k*a[i]]种情况,因为一开始是从1出发,所以最后输出b[1]即可

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int a[N];
int b[N];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	for(int i=1;i<=n;i++)
	b[i]=1;
	for(int i=n;i>=1;i--)
	{
		int k=1;
		while(i+k*a[i]<=n)
		{
			b[i]+=b[i+k*a[i]];
			b[i]%=998244353;
			k++;
		}
	}
	cout<<b[1]%998244353;
}

 E题 怎么这么多bug!?

当时没有时间看。。以为很难的,结果是个dp,dp[j][k]表示某个学生打了j行代码,出现了k个bug所有的情况种类。那么显然dp[0][0]=1;接下来就是状态转移,第一层遍历学生(会有n个学生,需要将dp增大),第二层遍历代码行数,第三层遍历会出现的bug数,最后ans将每个学生有可能写bug的情况都加起来

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,m,b,p;
int a[N];
int dp[N][N];
int main()
{
	int ans=0;
	cin>>n>>m>>b>>p;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	for(int k=a[i];k<=b;k++)
	dp[j][k]=(dp[j][k]+dp[j-1][k-a[i]])%p;
	for(int i=0;i<=b;i++)
	ans=(ans+dp[m][i])%p;
	cout<<ans<<endl;
}

 寒假集训天梯赛1

C题 宝藏

是个dp没错了,好像背包,但是条件好像多了一点,

一开始是这么想的没错,可是后来。。写了一个状态转移方程,可是一直不对,于是就走上歪路子了。。。

后来发现,其实是少了一个判定,对重物重量的遍历应该在外层,因为(i-1,j)和(i,j-1)不一定存在最大重量值,所以应该让k在不同值都遍历一次,这样就能解决最优方案的子方案不相邻的问题了

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,m,b,p;
int a[N];
int dp[N][N];
int main()
{
	int ans=0;
	cin>>n>>m>>b>>p;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	dp[0][0]=1;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	for(int k=a[i];k<=b;k++)
	dp[j][k]=(dp[j][k]+dp[j-1][k-a[i]])%p;
	for(int i=0;i<=b;i++)
	ans=(ans+dp[m][i])%p;
	cout<<ans<<endl;
}

 其他题目前还没头绪。。嘿嘿,未完待续......

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值