牛客练习赛123

牛客练习赛123

A.炸鸡块哥哥的粉丝题 

#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>s;
    for(int i=0;i<(n+1)/2;i++)
        cout<<s[i];
    return 0;
}

B.智乃想考一道鸽巢原理 

【题解】牛客练习赛123

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const int INF = 0x7fffffff;
const double eps = 1e-5;

int t,n,a[N];
int max1,max2,maxa,mi;
long long sum=0;

void solve() {
    max1=max2=-INF;
    sum=0;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        sum+=a[i];
        if(a[i]>max1){
            max1=a[i];//求最大值
            mi=i;
        }
    }
    if(n==1) {//特判1
        cout<<1<<endl;
        return;
    }
    for(int i=0;i<n;i++){
        if(i!=mi) max2=max(max2,a[i]);//求第二大值
    }
    for(int i=0;i<n;i++){//重点 鸽巢原理
        maxa=(max1==a[i])?max2:max1;
        if(sum-a[i]-maxa>=maxa-1) {
            if(a[i]>((sum-a[i])%2)) cout<<1<<' ';
            else cout<<0<<' ';
        }
        else {
            if(a[i]>(2*maxa-sum+a[i])) cout<<1<<' ';
            else cout<<0<<' ';
        }
    }
    cout<<endl;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

C. 智乃想考一道完全背包(Easy version)

分析:因为要保证a1​≤a2​≤...≤aK​≥...≥aN,所以当取除ak外的任意一件物品时,必须先取一件ak

换一句话来说,如果位置 k上的物品本来就很好了,那么肯定选这个物品就行了。但是如果有个很好的物品远离位置 k,那么我们就需要选上从这个位置到 k 上的所有物品,才能选上这一个物品,它就相当于和中间的物品进行捆绑销售了。

反正一定会捆绑销售,所以我们不如一开始就将 l ∼ k 或 k ∼ r位置上的物品进行绑定,把它们变成一个物品,然后跑完全背包。

不过由于我们选了 l ∼ k 的物品的话,我们还能去拓展另一边到 r rr,并省下一个 k。所以另一边我们也需要绑定过来,也就是说需要把 l ∼ r上的物品进行绑定。

如果我们以位置为横坐标,每个位置上物品选择的个数为纵坐标画直方图的话,它的形状就是一个金字塔型。我们绑定物品同时选取,其实就相当于绑定一行,每行都是整块选取。

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=2005;
const int maxm=505;
typedef long long ll;

int n,m,k;
ll dp[maxm];

ll tw[maxn],tv[maxn];

int main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++){
		cin>>tw[i]>>tv[i];
		tw[i]+=tw[i-1];
		tv[i]+=tv[i-1];
	}
	for(int l=1;l<=k;l++)
		for(int r=k;r<=n;r++){
			ll w=tw[r]-tw[l-1],v=tv[r]-tv[l-1];
			for(int j=w;j<=m;j++)
				dp[j]=max(dp[j],dp[j-w]+v);
		}
	
	for(int i=1;i<=m;i++){
		dp[i]=max(dp[i-1],dp[i]);
		cout<<dp[i]<<" ";
	}
	return 0;
}

 D.智乃想考一道完全背包(Hard version)

分析: 

 

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2005, MAXM = 505;
long long w[MAXN], v[MAXN], dp[MAXN][MAXM], ans[MAXN][2];
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i)
    {
        scanf("%lld %lld", &w[i], &v[i]);
    }
    for (int i = 1; i <= n; ++i)
    {
        w[i] += w[i - 1];
        v[i] += v[i - 1];
        ans[i][1] = 1;
    }
    // 整体枚举思路
    // 固定i,枚举区间[i,n], [i,n-1], ... [i,i]
    // 我们发现,因为是从后往前枚举,确保最后 取的数量 a[i]>=a[i+1]>=...>=a[n]
    // 其次,i从后往前递增,
    // 我们发现,此时保证了当下一个递增顶点从i变成了i+1时,保证a[i]>=a[i-1]   
    // 通过外部、内部两层循环,优雅的实现了a[1]<=a[2]<=...a[K]>=a[K+1]>=...>=a[n]
    for (auto i = 1; i <= n; ++i) // 枚举从i做为 取值顶点时的最大价值
    {
        for (auto j = n; j >= i; --j) // 从后往前枚举
        {
            // 这里w[j]-w[i-1]表示 是否取[i,j]的区间元素,且元素是无限个
            long long W = w[j] - w[i - 1];
            long long V = v[j] - v[i - 1];
            for (auto k = W; k <= m; ++k) // 完全背包,所以从前往后枚举
            {
                dp[j][k] = max({dp[j][k], dp[j + 1][k], dp[j][k - W] + V});
            }
        }
        for (auto j = 0; j <= m; ++j)
        {
            if (dp[i][j] > ans[j][0]) // 更新容量为j的最优值
            {
                ans[j][0] = dp[i][j];
                ans[j][1] = i;
            }
        }
    }
    for (auto i = 1; i <= m; ++i)
    {
        printf("%lld%c", ans[i][0], " \n"[i == m]);
    }
    for (auto i = 1; i <= m; ++i)
    {
        printf("%lld%c", ans[i][1], " \n"[i == m]);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值