【题解】Educational Codeforces Round 73 (Rated for Div. 2)

绝地灬酷狼 2023-06-19 15:26 94阅读 0赞

#

  • A. 2048 Game(思维)
  • B. Knights(构造)
  • C. Perfect Team(模拟)
  • D. Make The Fence Great Again(二维dp)

A. 2048 Game(思维)

原题链接:http://codeforces.com/contest/1221/problem/A

  • 题意: 2048游戏,有玩过的都懂。给你一列数字,都是2的次幂,这个数列中相同的数可以互相相加,相加之后两个加数去掉,把和放入数列。之后数列中相同的数字又可以相加。问这个数列在变换中有没有可能出现2048。
  • 思路: 比赛时想复杂了,两层循环实现,具体看代码吧,仅供参考!看了大佬的思路和代码才发现这题可以写得很简单。因为所有数都是 2 的次幂且 1+2+4…+1024 全部都只有一个,也只有2047,所以只要确保小于等于2048的数字相加后能大于等于2048即可。

Code1: 比赛时的代码,把所有情况考虑了一遍,代码看起来可能有点复杂。

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. typedef long long ll;
  5. ll a[105];
  6. int main(){
  7. int t; cin>>t;
  8. while(t--){
  9. int n; cin>>n;
  10. for(int i=1;i<=n;i++)
  11. cin>>a[i];
  12. sort(a+1,a+1+n);
  13. int vis=0;
  14. int flag=1;
  15. for(int i=1;i<=n;i++){
  16. ll sum=a[i];
  17. if(a[i]==2048){
  18. vis=1;
  19. break;
  20. }
  21. for(int j=i+1;j<=n;j++){
  22. if(a[j]<2048){
  23. sum+=a[j];
  24. if(sum==2048){
  25. vis=1;
  26. break;
  27. }
  28. else if(sum>2048) break;
  29. }
  30. else if(a[j]>2048){
  31. flag=0;
  32. break;
  33. }
  34. else{
  35. vis=1;
  36. break;
  37. }
  38. }
  39. if(vis) break;
  40. if(!flag) break;
  41. }
  42. if(!flag){
  43. cout<<"NO"<<endl;
  44. continue;
  45. }
  46. if(vis) cout<<"YES"<<endl;
  47. else cout<<"NO"<<endl;
  48. }
  49. return 0;
  50. }

Code2:

  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4. int q; cin>>q;
  5. while(q--){
  6. int n; cin>>n;
  7. int sum=0,x;
  8. for(int i=1;i<=n;i++){
  9. cin>>x;
  10. if(x<=2048) sum+=x;
  11. }
  12. if(sum>=2048) cout<<"YES"<<endl;
  13. else cout<<"NO"<<endl;
  14. }
  15. return 0;
  16. }

B. Knights(构造)

原题链接:http://codeforces.com/contest/1221/problem/B

  • 题意: 要在一个n*n的棋盘中放满黑方和白方的马,马走 ‘日’ 字,求出最优方案使得双方所有马的攻击次数最多。
  • 思路: 奇数行奇数列和偶数行偶数列放白马,其他放黑马。

Code:

  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4. int n; cin>>n;
  5. for(int i=1;i<=n;i++){
  6. for(int j=1;j<=n;j++){
  7. if((i%2==1&&j%2==1) || (i%2==0&&j%2==0))
  8. cout<<'W';
  9. else
  10. cout<<'B';
  11. }
  12. cout<<endl;
  13. }
  14. return 0;
  15. }

C. Perfect Team(模拟)

原题链接:http://codeforces.com/contest/1221/problem/C

  • 题意: a,b,c 三种人各 c,m,x 个,要求 3 人一队且每队必须至少有 a,b 各一个,问最多能组成多少队。
  • 思路: 因为 c,m 至少要有一个,所以取 c,m 较小值,然后乘以 3 与 c,m,x 三数之和比较。如果比总数大,说明 c,m 是充足的,所以只需要输出总数除以 3 的结果即可;如果小于等于总数,说明总数是充足的,所以只需输出 c,m 较小值乘以 3 的结果。

Code:

  1. #include <iostream>
  2. using namespace std;
  3. typedef long long ll;
  4. int main(){
  5. int q; cin>>q;
  6. while(q--){
  7. ll c,m,x;
  8. cin>>c>>m>>x;
  9. ll minn=min(c,m);
  10. if(c+m+x>=3*minn)
  11. cout<<minn<<endl;
  12. else
  13. cout<<(c+m+x)/3<<endl;
  14. }
  15. return 0;
  16. }

D. Make The Fence Great Again(二维dp)

原题链接:http://codeforces.com/contest/1221/problem/D

  • 题意: 给你 n 个格子的高度和提高该格子一个单位高度所需花费的价格,每个格子最多提高两点高度,问使得所有相邻格子不同高度时所需的最小花费。
  • 思路: 用二维数组 dp[i][j] 表示格子提高相应的高度所需的花费,j 有三种状态,分别为 0,1,2,然后三层循环遍历,不断地寻找相邻格子高度不相同时三种状态所需的最小花费,最后输出三种状态高度不相同时的最小花费。要注意的就是最后输出的时候要取消同步,否则会TLE。

Code:

  1. #include <iostream>
  2. using namespace std;
  3. typedef long long ll;
  4. const ll inf=2e18;
  5. const int N=3e5+10;
  6. ll dp[N][3],a[N],b[N];
  7. int main(){
  8. ios::sync_with_stdio(0); //要取消同步才不会TLE
  9. int t; cin>>t;
  10. while(t--){
  11. int n; cin>>n;
  12. for(int i=1;i<=n;i++){
  13. cin>>a[i]>>b[i];
  14. dp[i][0]=dp[i][1]=dp[i][2]=inf;
  15. }
  16. dp[1][0]=0; //第一个格子
  17. dp[1][1]=b[1];
  18. dp[1][2]=2*b[1];
  19. for(int i=2;i<=n;i++){
  20. for(int j=0;j<3;j++){
  21. for(int k=0;k<3;k++){
  22. if(a[i-1]+j!=a[i]+k) //如果相邻格子高度不相同
  23. dp[i][k]=min(dp[i][k],dp[i-1][j]+k*b[i]); //取花费小的
  24. }
  25. }
  26. }
  27. //取三种状态花费最小的
  28. cout<<min(dp[n][0],min(dp[n][1],dp[n][2]))<<endl;
  29. }
  30. return 0;
  31. }

发表评论

表情:
评论列表 (有 0 条评论,94人围观)

还没有评论,来说两句吧...

相关阅读