[nk] 2022牛客寒假算法基础集训营1 补题|题解

前言

根据难度系数补题,大概会补 ACDEFHIJL (因为我的学长也做了这么多题)

L.牛牛学走路

题意 :
模拟上下左右,问什么时候的距离最大

思路 :
对于样例 t t t n n n,范围乘起来不超过 1 e 5 1e5 1e5,所以想了想我们可以使用栈模拟

我们将 L R LR LR U D UD UD分为这两组,如果当前栈顶元素不同于当前的 S [ i ] S[i] S[i]那么我们

就开始计算,并且更新答案


但是其实不用栈来模拟,因为使用栈来模拟,对于计算答案的时候,我们总是需要想

一下,虽然思路清晰但是码量较大,所以我们不妨看一下别人的代码,显然他们也是

分了两组,但是使用的是两个变量进行计算,这样子就可以更好的Ac

MyCode
double cal(int x,int y){
	return x*x + y*y;
}
void solve()
{
	int n;cin>>n;
	string s;cin>>s;
	ans = 0 ;
	
	while(!xlen.empty()) xlen.pop();
	while(!ylen.empty()) ylen.pop();
	
	for(int i = 0 ; i< n;i ++ ){
		if(s[i] == 'L'  || s[i] == 'R'){
			if(xlen.empty()){
				xlen.push(s[i]);
                ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
				continue;
			}
			
			if(xlen.top() == s[i]){
				xlen.push(s[i]);
				ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
				continue;
			}else{
				ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
				xlen.pop();
                ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
			}
		}
		
		if(s[i] == 'U' || s[i] == 'D'){
			if(ylen.empty()){
				ylen.push(s[i]);
                ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
				continue;
			}
			if(ylen.top() == s[i]){
				ylen.push(s[i]);
				ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
				continue;
			}else{
				ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
				ylen.pop();
                ans = max(sqrt(cal(xlen.size(),ylen.size())),ans);
			}
		}
	}
	printf("%.12lf\n",ans);
}
OtherCode
double get_dist(int x, int y){
    return sqrt(x * x + y * y);
}
 
void solve() {
    int n;
    cin >> n;
    int x = 0, y = 0;
    double res = 0;
    for(int i = 0 ; i < n ; i ++) {
        char c;
        cin >> c;
        if(c == 'L') x --;
        else if(c == 'R') x ++;
        else if(c == 'U') y ++;
        else y --;
        res = max(res, get_dist(x, y));
    }
    cout << fixed << setprecision(10) << res << "\n";
}
 
J.小朋友做游戏

题意 :
给你 A 和 B 两组小朋友,B的小朋友不能连在一起
我们需要选出 n 个人,使得价值最大

思路 :
显然因为 A 的小朋友不会打架,所以我们可以从 A 的小朋友这里入手 , 对于当前的状

态,如果确定A的数量为 ia 那么B的数量一定是 n-ia

当且仅当 : ( n − i a < m i n ( n / 2 , b ) ) & & ( n − i a ) > 0 (n-ia < min(n/2,b)) \&\&(n-ia) >0 (nia<min(n/2,b))&&(nia)>0

这个条件保证了,在 B B B数量够的情况下,确保一定不会出现相连的情况

但是这种情况下还需要考虑价值最大 :

所以我们需要对两个价值数组排序+前缀和处理一下

这样子在每次拿的情况下,我们 就是尽可能多的拿


我的思路太混乱了,不够简洁。所以在做的时候,一开始歪成了 d p [ N ] [ 2 ] dp[N][2] dp[N][2],利用

状态机进行逐个 d p dp dp,但是因为没有审题的原因,没发现是环状,所以总会贪心的多

拿一个 b b b,所以就歪了好久

MyCode
bool cmp(int a,int b){
	return a>b;
}

void solve()
{
	cin>>a>>b>>n;
	for(int i=1;i<=a;i++) cin>>va[i];
	for(int i=1;i<=b;i++) cin>>vb[i];
	
	sort(va+1,va+1+a,cmp);sort(vb+1,vb+1+b,cmp);
	/**
	判断不能的情况 
	**/	
	int ans =  -1 ;
	
	if(a < (n+1)/2){cout<<-1<<endl;return;}
	
	for(int i=1;i<=a;i++) suma[i] = suma[i-1]+ va[i];
	for(int i=1;i<=b;i++) sumb[i] = sumb[i-1]+ vb[i];
	
	for(ia = 0 ;ia<=a;ia++){
		ib = n-ia;
		if(ib>min(n/2,b)) continue;
		if(ib<0)continue;
		ans = max(ans,suma[ia]+sumb[ib]);
	}
	if(ans==-1)
	cout<<-1<<endl;
	else
	cout<<ans<<endl;
	
}
A.九小时九个人九扇门

思路 :
背包问题求方案数,首先多弄几组你就会发现 数字根 = X%9

所以我们可以使用老方法 :

状态表示 : f [ i ] [ j ] f[i][j] f[i][j] i i i个物品里面选价值是 j j j的方案数

初始化 f [ 0 ] [ 0 ] = 1 f[0][0]=1 f[0][0]=1,然后通过枚举 j j j来进行状态计算即可

MyCode
typedef priority_queue<int,vector<int>,greater<int>>  Pri_m;
typedef pair<int,int> pii;
typedef vector<int> VI;
map<int,int> mp;

const int N  = 1e5+10,MOD = 998244353;
int f[N][10],a[N];
int n;
inline void cal(int i,int x){
	if(x<10) {
		a[i]  = x;
		return;
	}
	a[i] = x%9;
}
void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		cal(i,x);
	}
	
	f[0][0] = 1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=8;j++ ){
			f[i][(a[i]+j)%9] = (f[i][(a[i]+j)%9] + f[i-1][j])%MOD;
			f[i][j] = (f[i-1][j] + f[i][j])%MOD;
		}
	}
	
	for(int i=1;i<=8;i++)
	cout<<f[n][i]<<' ';
	cout<<f[n][0]-1<<endl;
	
}
/**mYHeart is my algorithm**/
int main()
{
    //int t;cin>>t;while(t -- )
    solve();
    return 0;
}
F. 中位数切分

思路 :
贪心的去想,两两分成一组,如果大于 m m m贡献加一否则减一

MyCode
void solve()
{
	int n,m;cin>>n>>m;
	int ans = 0 ;
	
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		if(x >= m) ++ans;
		else --ans;
	}
	if(ans > 0 )cout<<ans<<endl;
	else cout<<-1<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值