【华为机试】牛客网

牛客链接

https://www.nowcoder.com/ta/huawei

素数伴侣 :【匈牙利算法:最大二分匹配】

题目链接


百度百科

二分图:将节点分成两组,A和B,边都是横跨在两组之间的,组内是没有边的相连的

判断方法,染色法

匹配:边的集合,任意两个边都没有公共的节点

最大匹配:找出匹配的边集合最大

匈牙利算法

交错路
增广路径
需要证明的是没有增广路径的时候就是最大匹配了

知乎一篇写的很不错的文章
https://zhuanlan.zhihu.com/p/96229700

看了这个算法,用了男女生匹配的方式进行讲解,其实match函数就是在找增广路径
增广路径要以没有匹配的节点开始,
所以match(i)的时候,i前面的要么是已经match了
要么就是考虑过了,没法match
如果match(i) 返回是真,那么就是说还存在增广路径
否则就是考虑到i的最大匹配了

正常来说,我们应该考虑所有的情况,最后挑一个最大的匹配
这里复杂度变低的原因就是,算法只从前到后运行一次
增广路径不可能往前找,满足贪心的性质,所以复杂度就低了


看懂题解之后 耗时23min

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>

using namespace std;

#define debug(x) cout<<#x<<": "<<(x)<<endl;

bool isp(int n){
    int s = sqrt(n);
    for(int i=2;i<=s;i++){
        if(n%i==0){
            return false;
        }
    }
    return true;
}

int b[100];
int g[100];
bool l[100][100];
int v[100];
int bc;
int gc;
int p[100];

bool findg(int bi){
    
    for(int gi=0;gi<gc;gi++){
        if( l[bi][gi] && v[gi]==0){
            v[gi] = 1;
            if( p[gi]==-1 || findg( p[gi] ) ){
                p[gi]=bi;
                return true;
            }
        }
    }
    return false;    
}

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        bc = 0;
        gc = 0;
        fill(p,p+100,-1);
        for(int i=0;i<n;i++){
            int a=0;
            scanf("%d",&a);
            if(a%2==0){
                b[bc++] = a;
            }else{
                g[gc++] = a;
            }
        }
        
        for(int i=0;i<bc;i++){
            for(int j=0;j<gc;j++){
                l[i][j] = isp(b[i]+g[j]);
            }
        }
        
        int cnt=0;
        for(int i=0;i<bc;i++){
            fill(v,v+100,0);
            if(findg(i)){
                cnt++;
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}

在这里插入图片描述


https://www.nowcoder.com/practice/5190a1db6f4f4ddb92fd9c365c944584?tpId=37&&tqId=21249&rp=1&ru=/ta/huawei&qru=/ta/huawei/question-ranking

HJ26 字符串排序

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

struct node{
    char c;
    int pos;
    node(char c,int pos):c(c),pos(pos){}
};

int main(){
    string str;
    
    while(getline(cin,str)){
        vector<node>a;
        
        auto kind = [=](char c){
            if(c>='A' && c<='Z'){
                return 1;
            }else if(c>='a' && c<='z'){
                return 0;
            }
            return 2;
        };
        
        for(int i=0;i<str.size();++i){
            if(kind(str[i])<2){
                a.push_back(node{str[i],i});
            }
        }
        
        auto cmp = [&](const node& x,const node& y){
            
            int xk = x.c + kind(x.c)*32;
            int yk = y.c + kind(y.c)*32;
            
            if( xk == yk ){
                return x.pos<y.pos;
            }else{
                return xk<yk;
            }
        };
        sort(a.begin(),a.end(),cmp);
        int k=0;
        for(int i=0;i<str.size();++i){
            if(kind(str[i])<2){
                str[i] = a[k++].c;
            }
        }
        cout<<str<<endl;
    }
    return 0;
}

HJ6 质数因子

题目

描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )


数据范围: 
输入描述:
输入一个整数

输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。最后一个数后面也要有空格。

示例1
输入:
180
复制
输出:
2 2 3 3 5
#include <iostream>
#include <cmath>

using namespace std;

using ll = long long;


int main(){
    ll n;
    cin>>n;
    if(n==1){
        cout<<1<<" ";
    }
    for(ll i=2;i<=sqrt(n);++i){
        while(n>1){
            if(n%i==0){
                cout<<i<<" ";
                n/=i;
            }else{
                break;
            }
        }
    }
    if(n>1){
        cout<<n<<" " ;
    }
    cout<<endl;
    
    return 0;
}

HJ74 参数解析

链接

在命令行输入如下命令:

xcopy /s c:\\ d:\\e,

各个参数如下:

参数1:命令字xcopy

参数2:字符串/s

参数3:字符串c:\\

参数4: 字符串d:\\e

请编写一个参数解析程序,实现将命令行各个参数解析出来。


解析规则:

1.参数分隔符为空格
2.对于用""包含起来的参数,如果中间有空格,不能解析为多个参数。比如在命令行输入xcopy /s "C:\\program files" "d:\"时,参数仍然是4个,第3个参数应该是字符串C:\\program files,而不是C:\\program,注意输出参数时,需要将""去掉,引号不存在嵌套情况。
3.参数不定长

4.输入由用例保证,不会出现不符合要求的输入
数据范围:字符串长度:
进阶:时间复杂度:,空间复杂度:
输入描述:
输入一行字符串,可以有空格

输出描述:
输出参数个数,分解后的参数,每个参数都独占一行

示例1
输入:
xcopy /s c:\\ d:\\e
复制
输出:
4
xcopy
/s
c:\\
d:\\e
#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main(){
    string s;
    getline(cin,s);
    int i=0;
    int n = s.size();
    int yc=0;
    vector<string>r;
    for(i=0;i<n;){
        if(s[i]==' '){
            ++i;
            continue;
        }else if(s[i]=='"'){
            ++i;
            int j = s.find('"',i);
            if(j==-1){
                break;
            }
            r.push_back(s.substr(i,j-i));
            i = j+2;
        }else{
            int j = s.find(' ',i);
            if(j==-1){
                break;
            }
            r.push_back(s.substr(i,j-i));
            i = j+1;
        }
    }
    if(i<n){
        r.push_back(s.substr(i));
    }
    
    cout<<r.size()<<endl;
    for(auto ss:r){
        if(ss[0]=='"'){
            cout<<ss.substr(1,ss.size()-2)<<endl;
        }else{
            cout<<ss<<endl;
        }
        
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值