牛客编程巅峰赛S2第8场 - 钻石&王者 题解

A题:
发现n的范围只有20,所以暴力枚举每一个物品取或者不取,作者用二进制状态压缩来解决此问题。
代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回总体积为V若干物品的最大总重量,如果g存在选择若干物品总体积为V的情况,返回-1
     * @param v int整型vector 
     * @param g int整型vector 
     * @param V int整型 
     * @return int整型
     */
    int Maximumweight(vector& v, vector& g, int V) {
        int n=v.size(),ans=-1;
        for(int i=0;i<(1<<n);i++){
            int s=0,t=0;
            for(int j=0;j<n;j++)
                if(i>>j&1){
                    s=s+v[j];
                    t=t+g[j];
                }
            if(s==V)ans=max(ans,t);
        }
        return ans;
    }
};

时间复杂度 O(2^n)

B题:
最大前缀与最大后缀匹配,就是KMP中的next[len]的定义,所以直接套用模板即可。
代码如下:

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

时间复杂度 O(n)

C题:
发现与普通的最短路不同,它的路程是乘起来的,所以中途可能会出现极大的数字但又不能取模。
所以,我们使用对数的一个性质log(a)+log(b)=log(a*b),讲乘法改为加法。
但是又有一个新的问题,long long的数值太小,无法预处理1000以内的组合数,但是我们有double啊,它的范围几乎刚刚包含1000以内最大的组合数,所以就用double存储,在跑最短路的同时,为了方便我们还可以同时记录最终的答案。
代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int整型 有n个城市
     * @param m int整型 有m条路径
     * @param s int整型 起始城市坐标
     * @param t int整型 终点城市坐标
     * @param edge int整型vector> 边的格式如下:[[u1,v1,a1,b1],[u2,v2,a2,b2],...]
     * @return int整型
     */
    long long M=(1e9)+7,f[510][510],g[510][510],jc2[1010][1010],dis[510],dis2[510],vis[510];
    double jc[1010][1010];
    int minDist(int n, int m, int s, int t, vector >& edge) {
        for(int i=0;i<=1000;i++){
            jc[i][0]=1;
            jc2[i][0]=1;
            for(int j=1;j<=i;j++){
                jc[i][j]=jc[i-1][j]+jc[i-1][j-1];
                jc2[i][j]=(jc2[i-1][j]+jc2[i-1][j-1])%M;
            }
        }
        memset(f,0x3f,sizeof(f));
        for(int i=1;i<=n;i++)f[i][i]=0;
        for(int i=0;i<m;i++){
            int u=edge[i][0],v=edge[i][1],a=edge[i][2],b=edge[i][3];
            f[u][v]=f[v][u]=log(jc[a][b]);
            g[u][v]=g[v][u]=jc2[a][b];
        }
        memset(dis,0x3f,sizeof(dis));
        dis[s]=0;
        dis2[s]=1;
        for(int i=1;i<=n;i++){
            int nw=0;
            for(int j=1;j<=n;j++)
                if(!vis[j]&&dis[j]<dis[nw])nw=j;
            vis[nw]=true;
            if(nw==t)break;
            for(int j=1;j<=n;j++)
                if(!vis[j]&&dis[nw]+f[nw][j]<dis[j]){
                    dis[j]=dis[nw]+f[nw][j];
                    dis2[j]=dis2[nw]*g[nw][j]%M;
                }
        }
        return dis2[t];
    }
};

时间复杂度 O(n^2)

#题解#
全部评论

相关推荐

双非坐过牢:非佬,可以啊10.28笔试,11.06评估11.11,11.12两面,11.19oc➕offer
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务