Codeforces Round #552 (Div. 3)

A. Restoring Three Numbers

题意:给出4个数,它们分别是 a+b,a+c,b+c,a+b+c,求a,b,c的值

思路:排序,前三个数两两相加减去第四个数可依次求得a,b,c的值

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=200;
int main()
{
    int x[5];
    for(int i=0;i<4;i+=1){
        scanf("%d",&x[i]);
    }
    sort(x,x+4);
    int a=x[0]+x[1]-x[3];
    int b=x[0]+x[2]-x[3];
    int c=x[3]-a-b;
    printf("%d %d %d\n",a,b,c);
    return 0;
}

B. Make Them Equal

题意:给你一个序列,问你是否可以选取一个最小的数使得序列中的每个元素加上或减去这个数(或不变)最终能使序列中的各个元素相等

思路:

      假设一个序列能找到一个数D,序列经过操作并且元素值都等于x,则原序列中的元素值最多只存在三种情况:

     1)ai=x-D

     2)ai=x+D

     3)ai=x

解题步骤如下:

  1. 对序列进行去重并排序,能发现若去重后的序列中元素的个数若>3,则不存在符合条件的D;
  2. 若序列元素个数为3,若c-b=b-a,则D=c-b;
  3. 若序列元素个数为2,如果b-a是奇数,则D=b-a;若b-a是偶数,则D=(b-a)/2;
  4. 若序列个数为1,则D=0;
#include<bits/stdc++.h>
using namespace std;
const int N=200;
int main()
{
    int n,x;
    vector<int> v;
    scanf("%d",&n);
    int vis[N];
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i+=1){
        scanf("%d",&x);
        if(!vis[x])
        {
            vis[x]=1;
            v.push_back(x);
        }
    }
    sort(v.begin(),v.end());
    if(v.size()>3)
        printf("-1\n");
    else if(v.size()==3)
    {
        if(v[2]-v[1]==v[1]-v[0])
            printf("%d\n",v[2]-v[1]);
        else
            printf("-1\n");
    }
    else if(v.size()==2)
    {
        if((v[1]-v[0])%2)
            printf("%d\n",v[1]-v[0]);
        else
            printf("%d\n",(v[1]-v[0])/2);
    }
    else
        printf("0\n");
    return 0;
}

 

C. Gourmet Cat

题意:Polycarp的猫每天会吃一样特定的食物,一、四、七吃鱼;二、六吃兔;三、五吃鸡;现在Polycarp手上分别有a,b,c份量的三种食物。他打算出去旅行,问你选择周几出行,能维持喂猫的天数最长?

思路:

1.先算出不考虑选择周几出发能喂猫的最长周期数 weeks=min({a/3,b/2,c/2})

2.从周日到周一,依次计算选择不同出发时间能维持的最长天数+7*weeks

#include<bits/stdc++.h>
using namespace std;
int main()
{
    vector<int> u(3),v(3);
    cin>>u[0]>>u[1]>>u[2];
    int full=min({u[0]/3,u[1]/2,u[2]/2});
    u[0]=u[0]-3*full;
    u[1]=u[1]-2*full;
    u[2]=u[2]-2*full;
    vector<int> idx({0,1,2,0,2,1,0});
    int ans=0;
    for(int i=0;i<7;i+=1)
    {
        int s=i;
        v=u;
        int Count=0;
        while(v[idx[s]]>0)
        {
            --v[idx[s]];
            s=(s+1)%7;
            Count+=1;
        }
        ans=max(ans,full*7+Count);
    }
    printf("%d\n",ans);
    return 0;
}

D. Walking Robot

题意:在一个一维坐标轴上,坐标上每个点都处在光照或黑暗中,一个机器人从0出发,能到达最远的地方是n。它有一颗电池还有一颗蓄电池。机器人每次移动能选择消耗其中一颗电池中的能源。如果机器人消耗电池中的电并且移动到一个处于光照的点上,那么机器人可以给蓄电池充一个单位的电量,前提是蓄电池中的电不能超过上限。问机器人能走到的最远距离是多少?

思路: 对每一步贪心,详情看代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int seg[N];
int main()
{
    int n,i,bat,acc;
    scanf("%d %d %d",&n,&bat,&acc);
    for(i=1;i<=n;i+=1){
        scanf("%d",&seg[i]);
    }
    int A=acc;
    int B=bat;
    for(i=1;i<=n;i+=1){
        if(seg[i]==1)
        {
            if(acc==A)
                acc--;
            else if(bat>0)
            {
                bat--;
                acc<A?acc=acc+1:acc;
            }
            else if(acc>0)
                acc--;
            else
                break;
        }
        else
        {
            if(acc>0)
                acc--;
            else if(bat>0)
                bat--;
            else
                break;
        }
    }
    printf("%d\n",i-1);
    return 0;
}

E. Two Teams

题意:有n个学生排成一列,他们各自有不同的能力数值。现在有两个教练,每个教练会选取一些学生加入他们的队伍,选取规则是:两个教练依次在还未分配队伍的学生里,先选取能力值最高的那名学生再以他为中心向两边选离他距离<=k的学生,直到所有学生被选完,输出最后每个学生的归属队伍。

 

思路:利用链表做删除操作,同时标记出队学生归属的队伍

#include<bits/stdc++.h>
using namespace std;
#define reset(x,y) memset(x,y,sizeof(x))
typedef long long ll;
const int N = 200005;
pair<int,int> a[N];
list< pair <int,int> > L;
list< pair <int,int> >::iterator it[N];
int vis[N],res[N];
int main()
{
    int n,k,tech=1;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i].first);
        a[i].second=i;
        L.push_back(a[i]);
        it[i]=--L.end();
    }
    sort(a+1,a+1+n);
    reset(vis,0);
    for(int i=n;i>=1;i--){
        int no=a[i].second;
        if(vis[no]) continue;
        list< pair <int,int> >::iterator l=it[no],r=it[no];
        int T=k;
        while(T--)
        {
            if(l!=L.begin())
                l--;
            if(r!=--L.end())
                r++;
        }
        r++;
        while(l!=r)
        {
            vis[l->second]=1;
            res[l->second]=tech;
            l=L.erase(l);
        }
        tech=3-tech;
    }
    for(int i=1;i<=n;++i){
        printf("%d",res[i]);
    }
    return 0;
}

F. Shovels Shop

思路:

首先要使花费最少,那么应该购买的商品应该是将价格从小到大排序的前K个商品;

关于优惠券的使用,应该选择购买同样数量商品前提下能减免的数量最多的那一张;

 

#include<bits/stdc++.h>
using namespace std;
#define reset(x,y) memset(x,y,sizeof(x))
typedef long long ll;
const int N = 200005;
const int INF=1e9;
int main()
{
    ios::sync_with_stdio(false);
    int n,m,k;
    cin>>n>>m>>k;
    vector<int> v(n);
    for(int i=0;i<n;++i){
        cin>>v[i];
    }
    sort(v.begin(),v.end());
    v.resize(k);
    reverse(v.begin(),v.end());
    vector<int> offer(k+1);
    for(int i=0;i<m;++i)
    {
        int x,y;
        cin>>x>>y;
        if(x<=k)
            offer[x]=max(offer[x],y);
    }
    vector<int> pre(k+1,0);
    for(int i=0;i<k;++i){
        pre[i+1]=pre[i]+v[i];
    }
    vector<int> dp(k+1,INF);
    dp[0]=0;
    for(int i=0;i<k;++i)
    {
        dp[i+1]=min(dp[i+1],dp[i]+v[i]);
        for(int j=1;j<=k;++j)
        {
            if(offer[j]==0)
                continue;
            if(i+j>k) break;
            dp[i+j]=min(dp[i+j],dp[i]+pre[i+j-offer[j]]-pre[i]);
        }
    }
    cout<<dp[k]<<endl;
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值