今天来复盘这场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分成为学员选手