zoukankan      html  css  js  c++  java
  • 牛客每日一题

    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
  • 相关阅读:
    Android文件操作总结
    SQLite优化方法
    Android之TabHost布局
    Android简单数据存储SharedPreferences
    Android之SharedPreferences权限
    Android布局大全
    context理解
    Android网络连接之HttpURLConnection和HttpClient
    Android之ContentProvider总结
    Intent的简介以及属性详解
  • 原文地址:https://www.cnblogs.com/wizarderror/p/12564608.html
Copyright © 2011-2022 走看看