2022.6.9 特长生模拟

这篇博客涵盖了四种不同的算法问题:安全密码的计算、农场主马房分配的最小系数求解、最短路径营救策略以及栅栏木料的优化搜索。通过循环、动态规划、宽度优先搜索和暴力搜索结合剪枝等算法,分别解决了这些问题。文章深入浅出地解析了每个问题的解决方案,并提供了相应的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2012 2012 2012 特长生
目录:

A.安全密码
B.农场主
C.营救
D.栅栏的木料

A . A. A.安全密码

在这里插入图片描述

分析:

直接循环 × × ×

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define reg register
using namespace std;
typedef long long ll;
ll a,b,c,ans=1,T; 
int main(){
	freopen("password.in","r",stdin);
	freopen("password.out","w",stdout);
	scanf("%d%d%d",&a,&b,&c);
	T=b;
	while(T--) (ans*=a)%=c;
	printf("%lld",ans);
	return 0;
}

B . B. B.农场主

在这里插入图片描述

分析:

d p dp dp
f i , j f_{i,j} fi,j表示建了 i i i个马房 分配了前 j j j只马的最小系数
那么就可以再枚举一个 k k k k < = i _{k<=i} k<=i
f i , j = m i n { f i , j , f i − 1 , k + s u m k , j } f_{i,j}=min\{f_{i,j},f_{i-1,k}+sum_{k,j}\} fi,j=min{fi,j,fi1,k+sumk,j} s u m k , j sum_{k,j} sumk,j就是 k , j k,j k,j马房间系数的和

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define reg register
using namespace std;
typedef long long ll;
const int N=505;
int n,k,a[N],qwq[N],awa[N],ans,sum[N][N],f[N][N];
int main(){
	freopen("farmer.in","r",stdin);
	freopen("farmer.out","w",stdout);
	memset(f,0x3f,sizeof f);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		(a[i])?qwq[i]=1:awa[i]=1;
		qwq[i]+=qwq[i-1];
		awa[i]+=awa[i-1];
	}
	for(int i=1;i<=n;i++)
		f[1][i]=qwq[i]*awa[i];
	for(reg int i=1;i<=n;i++)
	for(reg int j=1;j<=n;j++)
		sum[i][j]=(qwq[i]-qwq[j])*(awa[i]-awa[j]);
	for(reg int l=2;l<=k;l++)
	for(reg int i=l+1;i<=n;i++)
	for(reg int j=1;j<=i;j++)
		f[l][i]=min(f[l][i],f[l-1][j]+sum[i][j]);
	printf("%d",f[k][n]);
	return 0;
}

C . C. C.营救

在这里插入图片描述

分析:

b f s bfs bfs

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define reg register
using namespace std;
typedef long long ll;
const int N=1005;
int n,dx[6]={0,1,0,-1},dy[6]={-1,0,1,0},vis[N][N],sx,sy,ex,ey;
char a[N][N];
struct node{
	int x,y,step;
};
queue<node> q;
int bfs(int sx,int sy)
{
	q.push((node){sx,sy,0});
	while(!q.empty())
	{
		node x=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			int xx=x.x+dx[i],yy=x.y+dy[i];
			if(xx==ex&&yy==ey) return x.step+1;
			if(xx<1||xx>n||yy<1||yy>n||a[xx][yy]=='1'||vis[xx][yy]) continue;
			vis[xx][yy]=1;
			q.push((node){xx,yy,x.step+1});
		}
	}
}
int main(){
	freopen("save.in","r",stdin);
	freopen("save.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
		cin>>a[i][j];
	scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
	printf("%d",bfs(sx,sy));
	return 0;
}

D . D. D.栅栏的木料

在这里插入图片描述

在这里插入图片描述

分析:

暴搜和剪枝 + + + 二分答案
一个很显然的贪心思路就是用大木板去切小木料 以此基础暴搜

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define reg register
using namespace std;
typedef long long ll;
const int N=55;
int n,m,a[N],b[1055],ans,vis[N],sum[N],sum2[1055],tot,tmp,k[N];
bool dfs(int x,int last)
{
	if(x==0) return 1;
	if(b[x]^b[x+1]) 
		last=tot;
	for(int i=last;i<=n;i++)
		if(!vis[i]&&k[i]>=b[x])
		{
			k[i]-=b[x];
			if(k[i]<b[tot])
			{
				if(tmp<k[i])
				{
					k[i]+=b[x];
					continue;
				}
				tmp-=k[i];
				vis[i]=1;
				if(dfs(x-1,i)) return 1;
				tmp+=k[i];
				vis[i]=0;
			}
			else 
				if(dfs(x-1,i)) return 1;
			k[i]+=b[x];
		}
	return 0;
}
bool check(int x)
{
	if(sum[n]<sum2[x]) return 0;
	tmp=sum[n]-sum2[x];
	tot=1;
	while(a[tot]<b[1]&&tot<=n)
	{
		tmp-=a[tot];
		if(tmp<0) return 0;
		tot++;
	}
	for(int i=1;i<=n;i++) k[i]=a[i];
	memset(vis,0,sizeof vis);
	return dfs(x,1);
}
int main(){
	freopen("fence.in","r",stdin);
	freopen("fence.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
		sum[i]=sum[i-1]+a[i];
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
		scanf("%d",&b[i]);
	sort(b+1,b+m+1);
	for(int i=1;i<=m;i++)
		sum2[i]=sum2[i-1]+b[i];
	int l=1,r=m;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid))
		{
			ans=mid;
			l=mid+1;
		}
		else r=mid-1;
	}
	printf("%d",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值