Codeforces Round #683 题解(A~C)

A. Add Candies

题目链接:A题

题目大意:
共有n个包裹,第i个包裹初始时装有i颗糖果

你可以选择m次操作(m由自己决定),在第j次操作时指定某一个包裹不放糖果,其它包裹每个包裹装入j颗糖果

目的:使所有包裹糖果数相同

思路:

n次操作,在第j次操作时,指定第j个包裹即可

例:n为3时
第一轮指定1号包裹,第二轮指定2号包裹,第三轮指定3号包裹,则最终每个包裹都是1+2+3颗糖果

代码:

#include <iostream>
#include <cstdio>
using namespace std;
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
      int n;
      scanf("%d",&n);
      printf("%d\n",n);
      for(int i=1;i<n;i++)
          printf("%d ",i);
      printf("%d\n",n);
    }
    return 0;
}

B.Numbers Box

题目链接:B题

题目大意:

n*m的矩阵,每次操作可以让矩阵中相邻的两个元素的值同时乘上-1,你可以操作任意次,问你矩阵所有元素的和sum的值最大为多少

思路:

如果矩阵中值为负数的元素有偶数个,则一定都能将它们变为正值,如果矩阵中有0也可以,否则不管怎么消除,都会有一个元素始终为负值,在这种情况下选择绝对值最小的为负值就行

代码:

#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
 
 
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
      int n,m;
      scanf("%d%d",&n,&m);
      int num=0;
      int abs_min=100000;
      int ans=0;
      int flag=0;
      for(int i=0;i<n;i++)
         for(int j=0;j<m;j++){
             int temp;
             scanf(" %d",&temp);
             ans+=abs(temp);
 
             if(temp==0) flag=1;
             if(temp<0)  num++;
             abs_min=min(abs_min,abs(temp));
      }
      if(num%2&&!flag) ans-=2*abs_min;
      printf("%d\n",ans);
    }
    return 0;
}

C. Knapsack

题目链接:C题

题目大意:

给你n件物品,每件物品质量为wi,一个容量为W的背包,让你选择一种方案使物品的质量和大于W的一半且不能超过W

思路:

在n件物品中,质量大于w的物品我们肯定不会选,没有意义,所以直接不考虑它。如果有质量大于W的一半而小于W的物品,那我们只选这个物品就行。

也就是说现在考虑x个物品,每个物品质量都小于W的一半,要求它们的和超过W的一半的方案。

将所有物品质量从小到大排序,然后累加到质量和大于W的一半即可,因为没有一个物品的质量会大于W的一半,所以不用考虑加上这个物品后质量会超过W。

然后再判断一下质量和小于W的一半的情况,输出-1(无方案)即可

代码:

#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;

typedef struct{
   long long number;
   int index;
}node;

node num[200010];

bool cmp(node a,node b){
   return a.number<b.number;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
      long long n,W;
      scanf("%lld%lld",&n,&W);
      long long low=(W+1)/2;
      int flag=0,ans,cnt=0;
      for(long long i=1;i<=n;i++){
          long long temp;
          scanf(" %lld",&temp);
          if(temp>W) continue;
          if(temp>=low)  flag=1,ans=i;
          num[cnt].number=temp;
          num[cnt++].index=i;
      }
      if(flag) {printf("1\n%d\n",ans);continue;}
      sort(num,num+cnt,cmp);
      int pos;
      long long s=0;
      for(int i=0;i<cnt;i++){
          s+=num[i].number;
          if(s>=low){
             pos=i;
             break;
          }
      }
      if(s<low) {printf("-1\n");continue;}
      printf("%d\n",pos+1);
      for(int i=0;i<=pos;i++)
         i==pos?printf("%d\n",num[i].index):printf("%d ",num[i].index);

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值