补题日记(5)

1、通天之分组背包(关于分组背包的复习)

 看到这题我们就会想到分组背包这个模型。那么这题就很容易解决了,也是把背包里面的物品分成s组,每组可以最多选择一个,问可以选下的最大值。但是这题最麻烦的地方就是它的输入格式

我们可以用一个vector数组来存储。

const int N =1010;
vector<pair<int,int>>v[N];

for(int i =1;i<=n;++i){
    int a,b,c;
    cin>>a>>b>>c;
    v[c].push_back({a,b});
}

然后就是分组背包的板子了

for(int i = 1;i<=n;++i){
    for(int j =1;j<=m;++j){
        dp[i][j] = dp[i-1][j];
        for(auto k : v[i]){
            if(j>=k.first)dp[i][j] = max(dp[i][j] , dp[i-1][j-k.first]+k.second);
        }
    }
}

那么这题就做完了,以下是ac代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int dp[N][N];
vector<pair<int,int>>v[N];
int main(){
    int n,m;cin>>m>>n; //n个物品 书包总重量为m
    
    for(int i =1;i<=n;++i){
        int a,b,c;
        cin>>a>>b>>c;
        v[c].push_back({a,b});
    }
    for(int i =1;i<=n;++i){
        for(int j =1;j<=m;++j){
            dp[i][j] = dp[i-1][j];
            for(auto k : v[i]){
               if(j >= k.first) dp[i][j] = max(dp[i][j] , dp[i-1][j-k.first]+k.second);
            }
        }
        
    }
    
    cout<<dp[n][m];
    return 0;
}

2、codeforces (A - E)

A题

传送门:Problem - A - Codeforces

题意 : 给你三个数字 a 、 b 、 c 。其中两个相等,但第三个与其他两个不同。

请找出恰好出现一次的数值。

这题不需要用什么map,哈希。直接做就好了,非常简单

#include <bits/stdc++.h>
using namespace std;

int main(){
    int q;cin>>q;
    while(q--){
        int a[3];
        for(int i =1;i<=3;++i)cin>>a[i];
        if(a[1] == a[2])cout<<a[3]<<'\n';
        else if(a[1] ==a[3])cout<<a[2]<<'\n';
        else if(a[2] ==a[3])cout<<a[1]<<'\n';
    }
    
    return 0;
}

B题

传送门:Problem - B - Codeforces

题意:

拉丁方格是由字母 AA 、 BB 和 CC 组成的 3×33×3 网格:

  • 在每一行中,字母 AA 、 BB 和 CC 各出现一次,并且
  • 在每列中,字母 AA 、 BB 和 CC 各出现一次。

例如,一个可能的拉丁方格如下所示。

⎡⎣⎢ACBBACCBA⎤⎦⎥[ABCCABBCA]

给你一个拉丁方格,但是其中一个字母被换成了问号 ?? 。请找出被替换的字母。

这题相比于A题就比较麻烦了,我们得用一个二维数组存储一下方阵,然后找到?所在的那一行,然后我是用一个比较笨的方法找那个?是A还是B或C。这里直接上代码和注释


//此前我们已经找到了?在num行
    int t = 3;              //因为 A-A =0 B-A =1 C-A =2 他们加起来为3
    for(int i=0;i<3;++i){
        if(v[num][i] !='?'){
           t -= v[num][i] - 'A';   //我们让t减去他们的差值
        }
    }
    if(t == 0)cout<<'A'<<'\n';
    if(t == 1)cout<<'B'<<'\n';
    if(t == 2)cout<<'C'<<'\n';

这就是这题的难点,下面是ac代码

#include <bits/stdc++.h>
using namespace std;

void slove(){
    vector<string>v(3);
    for(int i =0;i<3;++i){
        cin>>v[i];
    }
    int num =0;
    for(int i =0;i<3;++i){
        for(int j =0;j<3;++j){
            if(v[i][j] =='?')num =i;
        }
    }
    //说明?在num行
    int t = 3;
    for(int i=0;i<3;++i){
        if(v[num][i] !='?'){
           t -= v[num][i] - 'A';
        }
    }
    if(t == 0)cout<<'A'<<'\n';
    if(t == 1)cout<<'B'<<'\n';
    if(t == 2)cout<<'C'<<'\n';
}


int main(){
    int _;cin>>_;
    while(_--)slove();
   return 0;
}

C题

传送门:Problem - C - Codeforces

这题唯一的难点就是判断一个数是不是平方数,那么怎么判断呢?从一开始枚举吗?枚举到多少呢?会超时吗?我们想一下,在c++int类型中 根号5会等于2 ,根号四也会等于2,但是2*2 = 4。

所以我们只需要开根号后再判断那个数平方是不是我们原来的数字就行了

以下还是ac代码

#include <bits/stdc++.h>
using namespace std;
using ll =long long;
void slove(){
    int n;cin>>n;
    ll sum =0;
    while(n--){
        ll x;cin>>x;
        sum +=x;
    }
    ll t =sqrt(sum);
    if(t * t ==sum)cout<<"YES"<<'\n';
    else cout<<"NO"<<'\n';
}


int main(){
    int q;cin>>q;
    while(q--){
        slove();
    }
    
    return 0;
}

D题

传送门:Problem - D - Codeforces

我认为D题是ABCDE当中最难的一道题了,为什么呢?(因为我不会写,太菜了),但是这道题目我现在会写了。这道题我们如果把情况都列出来:

CVCV

CVCCVC

CVCVC 

CVCCV

我们会发现一个规律,就是看第4个字母,如果是v的话那么从前面两个字母后面就开始加.  如果第四个字母是C的话,那么从第三个字母后面就开始加.

int get(char x) {
	if(x=='b' || x=='c' || x=='d') return 1;
	return 0;
}

if(get(s[i+3]) == 0){
           cout<<s[i]<<s[i+1]<<'.';
           i +=1;
       }
       else if(get(s[i+3]) ==1){
           cout<<s[i]<<s[i+1]<<s[i+2]<<'.';
           i +=2;

然后还需要判断一下最后走到最后两位或者三位的时候

if(i+2 == n-1){
           cout<<s[i]<<s[i+1]<<s[i+2];
           break;
       }
       if(i+1 == n-1){
           cout<<s[i]<<s[i+1];
           break;
       }

ac代码

#include <bits/stdc++.h>
using namespace std;
int get(char x){
    if(x =='a' || x == 'e')return 0;
    return 1;
}
void solve(){
    int n;cin>>n;
    string s;cin>>s;
    for(int i =0;i<n;++i){
        //特别要判定一下最后两位或者三位
        if(i+1 == n-1){
            cout<<s[i]<<s[i+1];
            break;
        }
        if(i +2 ==n-1){
            cout<<s[i]<<s[i+1]<<s[i+2];
            break;
        }
        if(get(s[i+3] )== 0){
            cout<<s[i]<<s[i+1]<<'.';
            i +=1;  
        }
        if(get(s[i+3]) == 1){
            cout<<s[i]<<s[i+1]<<s[i+2]<<'.';
            i +=2;
        }
        
    }
    cout<<'\n';
}

int main(){
    ios::sync_with_stdio,cout.tie(0),cin.tie(0);
    int _;cin>>_;
    while(_--)solve();
    return 0;
}

E题

传送门:Problem - E - Codeforces

E题还是比较简单的,我们可以定义一个sum,当枚举到奇数时,sum -=a[i],然后把他放到map里面,枚举到偶数时就+=a[i],然后放到map里,判断一下,如果之前map的这个位置也有数了,那么就代表这个sum重复了,那么就可以在这个区间里选到满足条件的。

#include <bits/stdc++.h>
using namespace std;
using ll =long long;
const int N = 2e5+9;
int a[N];
void solve(){
    int n;
    cin>>n;
    for(int i =1;i<=n;++i)cin>>a[i];
    map<ll ,ll>mp;
    mp[0] = 1;
    ll sum =0;
    for(int i=1;i<=n;++i){
        if(i&1)sum +=a[i];
        else sum -=a[i];
        if(mp[sum] ==1){
            cout<<"YES"<<'\n';
            return;
        }
        mp[sum] = 1;
    }
    cout<<"NO"<<'\n';
}

int main(){
    int _;
    cin>>_;
    while(_--)solve();
    return 0;
}

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值