牛客编程巅峰赛S2第8场

  • Post author:
  • Post category:其他


牛牛选物

链接:

https://ac.nowcoder.com/acm/contest/9887/A


牛牛有现在有n个物品,每个物品有一个体积v[i]和重量g[i],他想选择其中总体积恰好为V的若干个物品,想使这若干个物品的总重量最大,他想知道最大总重量为多少。(如果不存在合法方案,返回-1)

01背包,不过容量太大了,而物品数量却很小,所以用二进制枚举即可

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回总体积为V若干物品的最大总重量,如果g存在选择若干物品总体积为V的情况,返回-1
     * @param v int整型一维数组 
     * @param g int整型一维数组 
     * @param V int整型 
     * @return int整型
     */
    public int Maximumweight (int[] v, int[] g, int V) {
        // write code here
        int n=v.length;
        int ans=-1;
        for(int i=0; i<(1<<n); i++){/// 利用二进制法枚举子集,集合个数应当为 2^n
            long SumW, SumV;
            SumW = SumV = 0;
            for(int j=0; j<n; j++){
                if((i >> j & 1)!=0){
                    SumW += g[j];
                    SumV += v[j];
                }
            }
            if(SumV==V&&SumW>ans)
                ans=(int)SumW;
        }
        return ans;
    }
}

牛牛与字符串2

链接:

https://ac.nowcoder.com/acm/contest/9887/B

牛牛拿到了一个字符串。他想知道除去字符串本身以外,这个字符串最大的公共前后缀的长度是多少?

例如,对于字符串ABABA而言,“ABA”即是它的前缀,也是它的后缀,且是最长的公共前后缀,因此最大的长度是3。

牛牛无法解决该问题,所以他只好向你求助,给定一个只包含大写字母的字符串s,返回除去字符串本身以外公共前后缀最大长度,如果没有任何一个公共前后缀满足要求,返回-1即可。

很明显的最长前缀后缀长度,KMP next数组问题,这里是简化版:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 给定一个字符串s,返回具有相同前缀后缀的子串的第二大长度,反之,返回-1即可。
     * @param s string字符串 代表题意中的字符串s
     * @return int整型
     */
    public int solve (String s) {
        // write code here
        int t=0;
        for(int i=1;i<s.length();++i){
            if(s.charAt(i)==s.charAt(t)){
                t++;
            }else{
                if(s.charAt(i)==s.charAt(0)) t=1;
                else t=0;
            }
        }
        if(t==0)
            return -1;
        return t;
    }
}

当然也可以用字符串hash来做

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 给定一个字符串s,返回具有相同前缀后缀的子串的第二大长度,反之,返回-1即可。
     * @param s string字符串 代表题意中的字符串s
     * @return int整型
     */
    public int solve (String s) {
        // write code here
        int n = s.length();
        int base = 131, mod = 1000000007,mul = 1;
        int left = 0, right = 0;
        int ans = -1;
        for (int i = 0; i < n; ++i) {
            left = (int) (((long) left * base + s.charAt(i)) % mod);
            right = (int) ((right + (long) mul * s.charAt(n-1-i)) % mod);
            if (i!=n-1&&left == right) {
                ans = i+1;
            }
            mul = (int) ((long) mul * base % mod);
        }
        return ans;
    }
}

牛牛送快递

链接:

https://ac.nowcoder.com/acm/contest/9887/C


牛牛为了向牛妹表达爱意,决定亲自给牛妹送上礼物。牛牛住在城市s\mathit ss,而牛妹住在城市t\mathit tt(牛牛和牛妹并不在同一座城市)。牛客国一共有n\mathit nn座城市,这n\mathit nn城市之间有m\mathit mm条城际高速可以让连接的城市相互通行。在牛客国,人们喜欢用组合数CabC_a^bCab​来计数,所以通过某一条城际高速所需要的过路费也是用CabC_a^bCab​来表示的。并且牛客国比起加法,更偏爱乘法,所以从城市s\mathit ss到达城市t\mathit tt所需要的总花费为路径上经历过的城际高速过路费之积,即∏i∈s→tCaibi\prod _{i\in s\rightarrow t}C_{a_i}^{b_i}∏i∈s→t​Cai​bi​​。牛牛了省钱想让你帮助他规划一条花费最少的路线,并把总花费告诉牛牛。由于答案可能很大请对109+710^9+7109+7取模。

题目要求无向图中乘积的最小值路径,这里可以把乘法转化位对数运算的加法loga+logb=logab,然后直接用Dijkstra求即可,最后还原可能会有精度问题,不过这里数据比较友好,不用担心这个问题:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int整型 有n个城市
     * @param m int整型 有m条路径
     * @param s int整型 起始城市坐标
     * @param t int整型 终点城市坐标
     * @param edge int整型vector<vector<>> 边的格式如下:[[u1,v1,a1,b1],[u2,v2,a2,b2],...]
     * @return int整型
     */
    
    typedef pair<double,int>pi;
    typedef pair<int,int>Pi;
    typedef pair<int,double>P;
    typedef long long ll;
    ll INF = 0x3f3f3f3f3f3f3f3f;
    static const int N = 100010;
    ll mod = 1000000007;
    double cc[1010][1010];
    ll C[1010][1010];
    int vis[N];
    double dis[N];
    ll ans[N];
    vector<P>G[N];
    map<Pi,Pi>mp;
    void Dijkstra(int s,int t,int n,int m){
        priority_queue<pi,vector<pi>,greater<pi>>que;
        que.push(pi(0,s));
        for(int i = 1;i <= n;i++)dis[i] = INF,vis[i] = 0;
        dis[s] = 0;
        ans[s] = 1;
        while(!que.empty()){
            pi p = que.top();
            que.pop();
            int u = p.second;
            if(vis[u])continue;
            vis[u] = 1;
            for(auto it : G[u]){
                int v = it.first;double w = it.second;
                if(!vis[v] && dis[v] > dis[u] + w){
                    dis[v] = dis[u] + w;
                    Pi pp = mp[Pi(u,v)];
                    ans[v] = ans[u] * C[pp.first][pp.second] % mod;
                    que.push(pi(dis[v],v));
                }
            }
        }
    }
    int minDist(int n, int m, int s, int t, vector<vector<int> >& edge) {
        // write code here
        for(int i = 0;i <= 1000;i++)cc[i][0] = C[i][0] = 1;
        for(int i = 1;i <= 1000;i++){
            for(int j = 1;j <= i;j++){
                C[i][j] = (C[i-1][j-1] + C[i-1][j]) % mod;
                cc[i][j] = cc[i-1][j-1] + cc[i-1][j];
            }
        }
        
        for(int i = 0;i < edge.size();i++){
            int u,v,a,b;u = edge[i][0],v = edge[i][1],a = edge[i][2],b = edge[i][3];
            double w = log2(cc[a][b]);
            mp[Pi(u,v)] = mp[Pi(v,u)] = Pi(a,b);
            G[u].push_back(P(v,w));
            G[v].push_back(P(u,w));
        }
        Dijkstra(s,t,n,m);
        
        return ans[t];
    }
};



版权声明:本文为qq_35513792原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。