牛客每日一题

tokitsukaze and Soldier  2020.3.25  

题意:

给定$n$个物品,每个物品有价值$v_i$和限制数量$s_i$表示选取物品的总个数不超过$s_i$,求最大价值

思路:

我一开始想的是$dp$,$WA$了后才意识到这样不可取

枚举选择多少件物品,显然所有不低于此限制的物品都能被选择,具体做法是:

物品按照$s_i$从大到小排序,然后枚举$s_i$,用堆保留最大的$s_i$件物品。时间复杂度为$O(nlogn)$

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#define ll long long 
#define inf 4e18
using namespace std;
const int maxn = 1e5+100;
int n;
priority_queue<ll, vector<ll>, greater<ll> > que;
struct node{
    int v, s;
}a[maxn];
bool cmp(node x, node y){
    return x.s > y.s;
}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d%d", &a[i].v, &a[i].s);
    sort(a+1, a+1+n, cmp);
    ll ans = 0, sum = 0;
    for(int i = 1; i <= n; i++){
        sum += a[i].v; que.push(a[i].v);
        while(que.size()>a[i].s){
            sum -= que.top();
            que.pop();
        }
        ans = max(ans, sum);
    }
    printf("%lld", ans);
}
 
View Code

合并回文子串  —2020.3.26

题意:

给定$a, b$两个字符串,将他们合并成字符串$c$,且保证$c$中各字符在原串中的相对位置不变,求$c$最长回文子串的长度

思路:

说实话拿到这题看了半天并没有思路,还是得看题解

巨佬说看到数据范围可以想到区间$dp$,结合这类题目要求解的答案好像的确是这样的

我们用$f[l1][r1][l2][r2]$来表示在$s1$中选取$s1_{l1}$到$s1_{r2}$,在$s2$种选取$s2_{l1}$到$s2_{r2}$是否能构成回文串

 考虑转移,由于字符串终串中字符的相对位置不能改变,所以只有这四种可能的转移:

最后需要注意的细节:

当两个字符串最多选出一个字符时,此时显然有$f[l1][r1][l2][r2]=1$,作为边界条件

#include <cstdio>
#include <cstring>
#include <algorithm>
#define pb push_back 
using namespace std;
char s1[55], s2[55];
int T, f[55][55][55][55];
int main(){
    scanf("%d", &T);
    while(T--){
        memset(f, 0, sizeof(f));
        scanf("%s%s", s1+1, s2+1);
        int len1 = strlen(s1+1), len2 = strlen(s2+1), ans = 0;
        for(int i = 0; i <= len1; i++){ //s1区间长度 
            for(int j = 0; j <= len2; j++){ //s2区间长度 
                for(int l1 = 1, r1 = l1+i-1; r1 <= len1; l1++, r1++){
                    for(int l2 = 1, r2 = l2+j-1; r2 <= len2; l2++, r2++){
                        if(i+j<=1) f[l1][r1][l2][r2] = 1; //边界 
                        else{
                            if(s1[l1]==s1[r1]) f[l1][r1][l2][r2] |= f[l1+1][r1-1][l2][r2];
                            if(s1[l1]==s2[r2]) f[l1][r1][l2][r2] |= f[l1+1][r1][l2][r2-1];
                            if(s2[l2]==s2[r2]) f[l1][r1][l2][r2] |= f[l1][r1][l2+1][r2-1];
                            if(s2[l2]==s1[r1]) f[l1][r1][l2][r2] |= f[l1][r1-1][l2+1][r2];
                        } 
                        if(f[l1][r1][l2][r2]) ans = max(ans, r1-l1+1+r2-l2+1);
                    }
                }
            } 
        }
        printf("%d
", ans);
    }
} 
View Code
原文地址:https://www.cnblogs.com/wizarderror/p/12564608.html