CodeTON Round 5 (Div. 1 + Div. 2, Rated, Prizes!)前三题复盘

今天来复盘这场div1+div2的比赛,我本人才疏学浅,只a了三个所以就只写了三个

第一题A. Tenzing and Tsondu

很明显这是一道博弈论的题目,细心一点就会发现,它其实胜负就只和选手A和B手中的怪物的血量总数有关,所以将输入便利一遍,谁的更大就输出谁,否则就输出Draw

下面是代码

import java.util.*;
import java.io.*;
public class Main{
    public static void main(String[] args)throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String s1=reader.readLine();
        int t=Integer.parseInt(s1);
        while(t-->0){
            String s2[]=reader.readLine().split(" ");
            int n1=Integer.parseInt(s2[0]);
            int n2=Integer.parseInt(s2[1]);
            long all1=0l,all2=0l;//all1为前一个选手的怪兽的血量和,all2同理
            String s3[]=reader.readLine().split(" ");
            String s4[]=reader.readLine().split(" ");
            for(int i=0;i<n1;i++){
                int e=Integer.parseInt(s3[i]);
                all1+=e;
            }
            for(int i=0;i<n2;i++){
                int e=Integer.parseInt(s4[i]);
                all2+=e;
            }
            //计算完成后进行比较输出结果即可
            if(all1>all2)System.out.println("Tsondu");
            else if(all1<all2)System.out.println("Tenzing");
            else System.out.println("Draw");
            
        }
    }
}

第二题B. Tenzing and Books

考察的是二进制和贪心运算

先将目标值的二进制搞出来,接着对三行书本依次进行便利,当前数字的每一二进制位都和目标值的二进制进行比如果可行,就将这个数字和预设好的数字进行运算。但对如果目标值的某一位是0,而当前数字的当前位上是1,则说明这个数字不可以进行或运算。如果这个数字不行,由题可知,这一行后面的数字都不进行考虑,直接break出去即可。

最后会发现 预设的数字如果和目标值相同则输出yes负责则no

import java.util.*;
import java.io.*;
public class Main {
    public static void main(String[] args)throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String s1=reader.readLine();
        int t=Integer.parseInt(s1);
        while(t-->0){
            String s2[]=reader.readLine().split(" ");
            int n1=Integer.parseInt(s2[0]);
            int x=Integer.parseInt(s2[1]);
            int a[]=new int[32]; //存放的是x的二进制码
            int end=0;
            for(int i=0;i<32;i++){
                if(((x>>i)&1)==1){
                    a[i]=1;
                }
            }
            int k=0;
            if(x==0)k=1;
            int b[]=new int[32];
            int count=0;
            for(int i=0;i<32;i++){
                if(a[i]==b[i])count++;
            }
            
            int t1=3;
            while(t1-->0){
                String s3[]=reader.readLine().split(" ");
                for(int i=0;i<n1;i++){
                    int d=Integer.parseInt(s3[i]);
                    if(fun(x, d)==true){//判断函数
                        end=end|d;//更新预设值
                        if(k==0&&end==x)k=1;
                    }
                    else break;//有不符合的就直接跳过这一整行数字
                }
 
            }
            if(end==x)System.out.println("Yes");
            else System.out.println("No");
            
        }
    }
    static boolean fun(int x,int d){
        for(int i=0;i<32;i++){//一一比对
            if(((x>>i)&1)==0&&((d>>i)&1)==1){
                return false;
            }
        }
        return true;
    }
}
#include<iostream>
using namespace std;
const int N = 1e4+10;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        long long n , x , res = 0;
        cin>>n>>x;
        for(int i = 0;i < 3;i++)
        {
            int l = 1;
            for(int j = 0;j < n;j++)
            {
                int t;
                cin>>t;
            if((t|x) == x&&l == 1) res |= t;
        else l = 0;
        }
    }
    if(res == x) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    }
    return 0;
}

第三题C. Tenzing and Balls

这个题如果暴力的话,不仅很难写而且绝对会爆空间

最优的解就是动态规划

每一个dp[i]都表示当只有前i个数时的最优解

接下来就考虑状态转移,

1.首先如果dp[i-1]大于dp[i],那么就更新dp[i];

2.该位置的数字与它第一次出现的位置可能会出现最大值,那么dp【i]=第一次出现的位置的前一个dp加i-第一次出现的位置+1;

3该位置的数字与它前一次出现的位置进行删除会产生新的最大值,那么dp【i】=上一次出现的位置的前一个dp加i-j+1;

4.该位置的数字与它前一次出现的进行合并(要求当前一个位置不是第一次出现的位置)dp【i】=上一次出现的位置的dp值加 I-上一次出现的位置

详情见代码注释

import java.util.*;
import java.io.*;
public class Main {
    public static void main(String[] args)throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String s1=reader.readLine();
        int t=Integer.parseInt(s1);
        while(t-->0){
            Map<Integer,Integer> map=new HashMap<Integer,Integer>();//记录每个数字第一次出现的位置
            Map<Integer,Integer> map1=new HashMap<Integer,Integer>();//记录每个数字第二次出现的位置
            String s2=reader.readLine();
            int n=Integer.parseInt(s2);
            String s3[]=reader.readLine().split(" ");
            int dp[]=new int[n+1];//状态转移数组
            for(int i=1;i<=n;i++){
                int e=Integer.parseInt(s3[i-1]);
                if(!map.containsKey(e)){
                    map.put(e, i);//如果没有记录过就添加进去
                    map1.put(e, i);//同理添加
                    dp[i]=dp[i-1];
                }
                else  {
                    dp[i]=Math.max(dp[map.get(e)-1]+i-(int)map.get(e)+1,Math.max(dp[i-1],dp[map1.get(e)-1]+i-(int)map1.get(e)+1 ));//dp选择出情况1,2,3的最大值
                    if(map.get(e)!=map1.get(e))dp[i]=Math.max(dp[i], dp[map1.get(e)]+i-map1.get(e));//情况四的最大值
                    map1.put(e, i);}//更新上一次出现的位置
            }
            System.out.println(dp[n]);
        }
            
    }
}

顺便记录一下这场打完后成功晋级1200分成为学员选手

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值