Codeforces Round #510 (Div. 2) A&B By cellur925

第一次CF祭==

由于太菜了只做了前两题==

因为在第一题上耗费时间太多了,我还是太菜了==。

A. Benches

time limit per test

1 second

memory limit per test

256 megabytes

There are nn benches in the Berland Central park. It is known that aiai people are currently sitting on the ii-th bench. Another mm people are coming to the park and each of them is going to have a seat on some bench out of nn available.

Let kk be the maximum number of people sitting on one bench after additional mm people came to the park. Calculate the minimum possible kk and the maximum possible kk.

Nobody leaves the taken seat during the whole process.

Input

The first line contains a single integer nn (1≤n≤100)(1≤n≤100) — the number of benches in the park.

The second line contains a single integer mm (1≤m≤10000)(1≤m≤10000) — the number of people additionally coming to the park.

Each of the next nn lines contains a single integer aiai (1≤ai≤100)(1≤ai≤100) — the initial number of people on the ii-th bench.

Output

Print the minimum possible kk and the maximum possible kk, where kk is the maximum number of people sitting on one bench after additional mm people came to the park.

一句话题意:对一个确定的数列增加元素,求增加元素后序列最大值k的最大值和最小值

观察样例发现,k的最大值一定是把所有元素加到数列中最大值的结果。

那么最小值呢?几乎40分钟都在思考这个,从二分想到平均数云云,都不对,后来突然想到,我们从宏观来审视这个问题,因为增加的元素是全部都要进数列的,所以我们求出最后数列的全部元素总和,除以数列项数即可。(看起来很小学奥数的算法结果想了很久。。。)

于是愉快的交,几分钟后就被hack了,非常不爽...原因写在了注释里。还是考虑情况不全面。

 1 #include<cstdio>
 2 #include<algorithm>
 3
 4 using namespace std;
 5
 6 int n,m,maxans,sum,minans;
 7 int a[200];
 8
 9 int main()
10 {
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++)
13     {
14         scanf("%d",&a[i]);
15         maxans=max(maxans,a[i]);
16         sum+=a[i];
17     }
18     sum+=m;
19     minans=max(maxans,(sum+n-1)/n);
20     //结果肯定不能比maxans小
21     // 面对不能整除的情况我们+1,然后为了让结果具有普适性,所以+n/n,但是又怕在整除的时候加多,所以-1
22     printf("%d %d",minans,maxans+m);
23     return 0;
24 }

B. Vitamins

time limit per test

2 seconds

memory limit per test

256 megabytes

Berland shop sells nn kinds of juices. Each juice has its price cici. Each juice includes some set of vitamins in it. There are three types of vitamins: vitamin "A", vitamin "B" and vitamin "C". Each juice can contain one, two or all three types of vitamins in it.

Petya knows that he needs all three types of vitamins to stay healthy. What is the minimum total price of juices that Petya has to buy to obtain all three vitamins? Petya obtains some vitamin if he buys at least one juice containing it and drinks it.

Input

The first line contains a single integer nn (1≤n≤1000)(1≤n≤1000) — the number of juices.

Each of the next nn lines contains an integer cici (1≤ci≤100000)(1≤ci≤100000) and a string sisi — the price of the ii-th juice and the vitamins it contains. String sisi contains from 11 to 33 characters, and the only possible characters are "A", "B" and "C". It is guaranteed that each letter appears no more than once in each string sisi. The order of letters in strings sisi is arbitrary.

Output

Print -1 if there is no way to obtain all three vitamins. Otherwise print the minimum total price of juices that Petya has to buy to obtain all three vitamins.

本题显然是背包类的dp了,但是我开始竟然写了模拟(???),后来发现7种情况可能不全有。。我太菜了。

看到两种好的做法:Chemist的,码量较大,但是很容易理解。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4
  5 using namespace std;
  6
  7 int n;
  8 int price[2000],val[2000];
  9 char Chemist[10];
 10 int dp[2000][2][2][2];
 11
 12 int main()
 13 {
 14     scanf("%d",&n);
 15     for(int i=1;i<=n;i++)
 16     {
 17         scanf("%d",&price[i]);
 18         scanf("%s",Chemist+1);
 19         for(int j=1;j<=strlen(Chemist+1);j++)
 20         {
 21             if(Chemist[j]==‘A‘) val[i]+=1;
 22             if(Chemist[j]==‘B‘) val[i]+=2;
 23             if(Chemist[j]==‘C‘) val[i]+=4;
 24         }
 25     }
 26     memset(dp,127,sizeof(dp));
 27     for(int i=0;i<=n;i++)
 28         dp[i][0][0][0]=0;//两个初值操作,必须有。
 29     for(int i=1;i<=n;i++)
 30     {
 31         for(int j=0;j<=1;j++)
 32             for(int l=0;l<=1;l++)//继承之上,必须有。
 33                 for(int r=0;r<=1;r++)
 34                     dp[i][j][l][r]=dp[i-1][j][l][r];
 35         if(val[i]==7)
 36         {
 37             for(int j=0;j<=1;j++)
 38                 for(int l=0;l<=1;l++)
 39                     for(int r=0;r<=1;r++)
 40                         dp[i][1][1][1]=min(dp[i-1][j][l][r]+price[i],dp[i][1][1][1]);
 41         }
 42         else if(val[i]==6)
 43         {//VITAMIN A可能有或没有 分开考虑
 44             for(int j=0;j<=1;j++)
 45                 for(int l=0;l<=1;l++)//从上一个转移来,就是带上当前的了,也就是决策
 46                     dp[i][0][1][1]=min(dp[i-1][0][j][l]+price[i],dp[i][0][1][1]);
 47             for(int j=0;j<=1;j++)
 48                 for(int l=0;l<=1;l++)
 49                     dp[i][1][1][1]=min(dp[i-1][1][j][l]+price[i],dp[i][1][1][1]);
 50         }
 51         else if(val[i]==5)
 52         {
 53             for(int j=0;j<=1;j++)
 54                 for(int l=0;l<=1;l++)
 55                     dp[i][1][0][1]=min(dp[i-1][j][0][l]+price[i],dp[i][1][0][1]);
 56             for(int j=0;j<=1;j++)
 57                 for(int l=0;l<=1;l++)
 58                     dp[i][1][1][1]=min(dp[i-1][j][1][l]+price[i],dp[i][1][1][1]);
 59         }
 60         else if(val[i]==4)
 61         {
 62             dp[i][0][0][1]=min(dp[i][0][0][1],dp[i-1][0][0][0]+price[i]);
 63             dp[i][0][0][1]=min(dp[i][0][0][1],dp[i-1][0][0][1]+price[i]);
 64             dp[i][0][1][1]=min(dp[i][0][1][1],dp[i-1][0][1][0]+price[i]);
 65             dp[i][0][1][1]=min(dp[i][0][1][1],dp[i-1][0][1][1]+price[i]);
 66             dp[i][1][0][1]=min(dp[i][1][0][1],dp[i-1][1][0][0]+price[i]);
 67             dp[i][1][0][1]=min(dp[i][1][0][1],dp[i-1][1][0][1]+price[i]);
 68             dp[i][1][1][1]=min(dp[i][1][1][1],dp[i-1][1][1][0]+price[i]);
 69             dp[i][1][1][1]=min(dp[i][1][1][1],dp[i-1][1][1][1]+price[i]);
 70         }
 71         else if(val[i]==3)
 72         {
 73             for(int j=0;j<=1;j++)
 74                 for(int l=0;l<=1;l++)
 75                     dp[i][1][1][0]=min(dp[i-1][j][l][0]+price[i],dp[i][1][1][0]);
 76             for(int j=0;j<=1;j++)
 77                 for(int l=0;l<=1;l++)
 78                     dp[i][1][1][1]=min(dp[i-1][j][l][1]+price[i],dp[i][1][1][1]);
 79         }
 80         else if(val[i]==2)
 81         {
 82             dp[i][0][1][1]=min(dp[i][0][1][1],dp[i-1][0][0][1]+price[i]);
 83             dp[i][0][1][1]=min(dp[i][0][1][1],dp[i-1][0][1][1]+price[i]);
 84             dp[i][1][1][0]=min(dp[i][1][1][0],dp[i-1][1][0][0]+price[i]);
 85             dp[i][1][1][0]=min(dp[i][1][1][0],dp[i-1][1][1][0]+price[i]);
 86             dp[i][0][1][0]=min(dp[i][0][1][0],dp[i-1][0][0][0]+price[i]);
 87             dp[i][0][1][0]=min(dp[i][0][1][0],dp[i-1][0][1][0]+price[i]);
 88             dp[i][1][1][1]=min(dp[i][1][1][1],dp[i-1][1][0][1]+price[i]);
 89             dp[i][1][1][1]=min(dp[i][1][1][1],dp[i-1][1][1][1]+price[i]);
 90         }
 91         else if(val[i]==1)
 92         {
 93             dp[i][1][0][0]=min(dp[i][1][0][0],dp[i-1][0][0][0]+price[i]);
 94             dp[i][1][0][0]=min(dp[i][1][0][0],dp[i-1][1][0][0]+price[i]);
 95             dp[i][1][0][1]=min(dp[i][1][0][1],dp[i-1][0][0][1]+price[i]);
 96             dp[i][1][0][1]=min(dp[i][1][0][1],dp[i-1][1][0][1]+price[i]);
 97             dp[i][1][1][0]=min(dp[i][1][1][0],dp[i-1][0][1][0]+price[i]);
 98             dp[i][1][1][0]=min(dp[i][1][1][0],dp[i-1][1][1][0]+price[i]);
 99             dp[i][1][1][1]=min(dp[i][1][1][1],dp[i-1][0][1][1]+price[i]);
100             dp[i][1][1][1]=min(dp[i][1][1][1],dp[i-1][1][1][1]+price[i]);
101         }
102     }
103     int ans=1e9;
104     for(int i=1;i<=n;i++)
105     //从每一个地方寻找!! 因为决策可能不在最后
106         ans=min(ans,dp[i][1][1][1]);
107     if(ans==1e9) printf("-1");
108     else printf("%d",ans);
109     return 0;
110 }

L_A的,精简代码,巧妙运用位运算,神仙做法。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4
 5 using namespace std;
 6
 7 int i,j,n,f[10],c,t,len;
 8 char vt[5];
 9
10 int main()
11 {
12     scanf("%d",&n);
13     memset(f,0x3f,sizeof(f));
14     f[0]=0;
15     for(i=1;i<=n;++i)
16     {
17         scanf("%d%s",&c,vt+1);
18         len=strlen(vt+1);
19         t=0;
20         for(j=1;j<=len;++j)
21             switch(vt[j])
22             {
23                 case ‘A‘:
24                     t|=1;
25                     break;
26                 case ‘B‘:
27                     t|=2;
28                     break;
29                 case ‘C‘:
30                     t|=4;
31                     break;
32             }
33         for(j=0;j<=7;++j)
34             f[t|j]=min(f[t|j],f[j]+c);
35     }
36     if(f[7]==0x3f3f3f3f) printf("-1");
37     else printf("%d",f[7]);
38     return 0;
39 }

二位神仙都用了1,2,4这类二进制表示的方法,我开始也想用的,只不过用了1,2,3就会gg了,因为相加后可能会有重复,用2^n的数字表示,肥肠好。

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9665128.html

时间: 2024-11-01 12:00:25

Codeforces Round #510 (Div. 2) A&B By cellur925的相关文章

Codeforces Round #510 (Div. 2) D. Petya and Array (权值线段树)

题目地址:http://codeforces.com/contest/1042/problem/D 题意:给你n个数,问有多少个区间的和的值小于t 分析:区间和问题,常常用到前缀和来进行预处理,所以先预处理出前缀和数组sum sum[i]代表前i个数的和,那么sum[i]的贡献就是,  当i<k<=n时,存在多少个k,使sum[k]<t+sum[i] 也就是求在[i+1,n]中,小于t+sum[i]的数有多少. 所以我们可以类比于询问一个数是区间第几大的方法,使用权值线段树来解决,这里因

Codeforces Round #510 (Div. 2) B. Vitamins

B. Vitamins 题目链接:https://codeforces.com/contest/1042/problem/B 题意: 给出几种药,没种可能包含一种或多种(最多三种)维生素,现在问要吃到这三种维生素买药最少花费是多少. 题解: 嗯...可以直接暴力: #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5+5; int n; int c[N]; char s[N][

Codeforces Round #510 (Div. 2)(A)

传送门:Problem A https://www.cnblogs.com/violet-acmer/p/9682082.html 题意: 公园里有n个沙滩,a[i]表示第i个沙滩初始人数,现有m个人可以到任意沙滩,在这m个人全部到达任意沙滩后,求沙滩最多人数的最大值和最小值 例如: 假设有n=5,m=3 a[i] = :1 2 3 4 5 沙滩人数最大化便是这m个人全到第5个沙滩上,a[5]=8,当前所有沙滩的最大值为8 使沙滩人数最大值尽量最小化,第一个人可以来到第一个沙滩,第二个人来到第二

Codeforces Round #536 (Div. 2)

目录 Codeforces Round #536 (Div. 2) A 题目大意 题解 卡点 C++ Code: B 题目大意 题解 卡点 C++ Code: C 题目大意 题解 卡点 C++ Code: D 题目大意 题解 卡点 C++ Code: E 题目大意 题解 卡点 C++ Code: F 题目大意 题解 卡点 C++ Code: Codeforces Round #536 (Div. 2) A 题目大意 给你一个\(n\times n(n\leqslant500)\)的矩阵,只包含.

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除