牛客网华为机试(持续更新ing)

 坐标移动

string str;
string sub=str.substr(0,n);//取得str的子串,从0坐标开始总计n个字符
sub=str.substr(index);//取得子串,从index下标开始的后半部分子串

stoi(string);// string向int 的转换
str.find("xxx")!=string::npos; //找到了目标子串

//pair的初始化
vec.push_back({data1,data2});
vec.push_back(make_pair(data1,data2));
vec.push_back(pair<type1,type2>(data1,data2));
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <string.h>
#include <cctype>
using namespace std;
bool bEffectiveMove(string str)
{
    if(!(str[0]=='A'||str[0]=='W'||str[0]=='S'||str[0]=='D')) return false;
    if(str.size()==2)
    {
        if(!isdigit(str[1])) return false;
    }
    if(str.size()==3)
    {
        if(!(isdigit(str[1])&&isdigit(str[2])) ) return false;
    }
    return true;
}
void ProcessMoves(vector<pair<string,int>>& moves)
{
    int x=0;
    int y=0;
    for(const auto elem:moves)
    {
        if(elem.first=="A") x-=elem.second;
        if(elem.first=="S") y-=elem.second;
        if(elem.first=="D") x+=elem.second;
        if(elem.first=="W") y+=elem.second;
    }
    
    cout<<x<<","<<y<<endl;
}
vector<pair<string,int>> GetMoves(string str)
{
    vector<pair<string,int>> moves;
    string::size_type pos=str.find(";");
    string piece;
    while(pos!=string::npos)
    {
        piece=str.substr(0,pos);
        
        if(bEffectiveMove(piece))
        {
            moves.push_back(pair<string,int>(piece.substr(0,1),stoi(piece.substr(1)) ) ) ;
        }
        
        str=str.substr(pos+1);
        pos=str.find(";");
    }
    
    
    return moves;
}
int main()
{
    vector<pair<string,int>> moves;
    string str;
    while(getline(cin,str))
    {
        moves=GetMoves(str);
        ProcessMoves(moves);
    }
    
    return 0;
}

字符串排序

错误的:

#include <iostream>
#include <string>
#include <string.h>
#include <cctype>
#include <map>
#include <algorithm>
using namespace std;
bool cmp(char lhs,char rhs)
{
    if(islower(lhs)&&isupper(rhs)) return (lhs)<(rhs+32);
    if(isupper(lhs)&&islower(rhs)) return (lhs+32)<(rhs);
    return lhs<rhs;
}
string ReverseStr(string str)
{
    string strRes;
    map<int,char> other;
    for(int i=0;i<str.size();++i)
    {
        if(!isalpha(str[i])) other[i]=str[i];
        else strRes.push_back(str[i]);
    }
    
    sort(strRes.begin(),strRes.end(),cmp);

    for(auto elem:other)
    {
        if(elem.first>=strRes.size()) strRes.push_back(elem.second);
        else strRes.insert(strRes.begin()+elem.first,elem.second);
    }
    return strRes;
}
int main()
{
    string str;
    while(getline(cin,str))
    {
        cout<<ReverseStr(str)<<endl;
    }
    
    return 0;
}

正确的:

btw,为什么牛客网每次提交相同的代码执行效率都不一样呢?

#include <iostream>
#include <string>
#include <string.h>
#include <cctype>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;

string ReverseStr(string str)
{
    string strRes;
    map<int,char> other;
    for(int i=0;i<str.size();++i)
    {
        if(!isalpha(str[i])) other[i]=str[i];
    }

    vector<string> vec;
    for(int i=0;i<26;++i) vec.push_back("");
    
    for(auto elem:str)
    {
        if(isupper(elem)) vec[elem-'A'].push_back(elem);
        if(islower(elem)) vec[elem-'a'].push_back(elem);
    }
    
    for(auto sub:vec) strRes.append(sub);

    for(auto elem:other)
    {
        if(elem.first>=strRes.size()) strRes.push_back(elem.second);
        else strRes.insert(strRes.begin()+elem.first,elem.second);
    }
    return strRes;
}
int main()
{
    string str;
    while(getline(cin,str))
    {
        cout<<ReverseStr(str)<<endl;
    }
    
    return 0;
}

查找兄弟单词

sort对string的操作问题

for(auto& elem : vecStrs)
{
    sort(elem.begin(),elem.end());
}

//为什么不加 & 就无法实现sort的效果呢?

错误的:

不能将 word 这个单词sort之后再去比较!!!

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
vector<string> GetBroNums(vector<string> vecStrs,string word)
{
    vector<string> res;
    vector<string> vec=vecStrs;

    for(auto& elem:vecStrs) sort(elem.begin(),elem.end());//vecStrs是排序后的
    sort(word.begin(),word.end());
    
    for(int i=0;i<vecStrs.size();++i)
    {
        if(vec[i]!=word && vecStrs[i]==word)
        {
            res.push_back(vec[i]);
        }
    }
   
    
    sort(res.begin(),res.end());
    
    
    return res;
}
int main()
{
    int n=0;
    scanf("%d",&n);
    
    vector<string> words;
    string word;
    for(int i=0;i<n;++i)
    {
        cin>>word;
        words.push_back(word);
    }
    
    cin>>word;
    
    //兄弟单词的个数与位置
    vector<string> res=GetBroNums(words, word);
    if(res.size()!=0)
    {
        cout<<res.size()<<endl;
    }
    
    
    int k=0;
    scanf("%d",&k);
    
    if(k<res.size())
    {
        cout<<res[k-1]<<endl;
    }
    
    return 0;
}

正确的:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
bool isFriend(string word1, string word2)
{
    if(word1==word2) return false;
    sort(word1.begin(),word1.end());
    sort(word2.begin(),word2.end());
    return word1==word2;
}
int main()
{
    int n=0;
    scanf("%d",&n);
    
    int count=0;
    
    vector<string> words;
    string word;
    for(int i=0;i<n;++i)
    {
        cin>>word;
        words.push_back(word);
    }
    sort(words.begin(),words.end());
    
    //单词x
    cin>>word;
    int k;
    scanf("%d",&k);
    string kth;
    
    for(int i=0;i<words.size();++i)
    {
        if(isFriend(word,words[i])) 
        {
            ++count;
            if(count==k)
            {
                kth=words[i];
            }
        }
    }
    cout<<count<<endl;
    if(k<=count)
    {
        cout<<kth<<endl;
    }
    
    return 0;
}

字符串加密

string 字符的大小写转换

str[i]=tupper(str[i]);
str[i]=tolwer(str[i]);

 或者直接ascii码的加减,注意大写字母比对应的小写字母 小32!

#include <iostream>
#include <string>
#include <cctype>
using namespace std;
//加密
string Encrypt(string str0)
{
    string str=str0;
    
    for(int i=0;i<str.size();++i)
    {
        if(isdigit(str[i]))
        {
            if(str[i]=='9') str[i]='0';
            else str[i]+=1;
        }
        if(isalpha(str[i]))
        {
            if(isupper(str[i]))
            {
                if(str[i]=='Z') str[i]='a';
                else{
                    str[i]+=1;
                    str[i]=tolower(str[i]);
                }
            }
            else{
                if(str[i]=='z') str[i]='A';
                else{
                    str[i]+=1;
//                     str[i]+=32; 小写+32必然乱码了
                    str[i]=toupper(str[i]);
                }
            }
        }
        
    }
    return str;
}
//解密
string  Decrypt(string str0)
{
    string str=str0;
    
    for(int i=0;i<str.size();++i)
    {
        if(isdigit(str[i]))
        {
            if(str[i]=='0') str[i]='9';
            else str[i]-=1;
        }
        if(isalpha(str[i]))
        {
            if(isupper(str[i]))
            {
                if(str[i]=='A') str[i]='z';
                else{
                    str[i]-=1;
                    str[i]=tolower(str[i]);
                }
            }
            else{
                if(str[i]=='a') str[i]='Z';
                else{
                    str[i]-=1;
//                     str[i]-=32; 
                    str[i]=toupper(str[i]);
                }
            }
        }
        
    }
    
    return str;
}
int main()
{
    string str1,str2;
    cin>>str1>>str2;
    cout<<Encrypt(str1)<<endl;
    cout<<Decrypt(str2)<<endl;
    return 0;
}

落地小球运动距离与反弹高度

#include <iostream>
using namespace std;
int main()
{
    int height=0;
    scanf("%d",&height);
    
    //第五次落地,设第0次弹起height高
    double distance=0.0;
    double dBounce=height;
    double dDrop=height;
    
    for(int i=0;i<5;++i)
    {
        distance+=dDrop;
        dBounce=dDrop/2.0;
        distance+=dBounce;
        dDrop=dBounce;
    }
    distance-=dBounce;
    printf("%f\n",distance);
    printf("%f\n",dBounce);
    
}

称砝码(attention)

参考这位大佬的做法 称砝码_牛客博客

为什么牛客网上不能用 for ( auto & elem : set ) 呢?

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
int main()
{
    int iTypes;
    scanf("%d",&iTypes);

    vector<int> vecUnitMass;
    int iMass;
    for(int i=0;i<iTypes;++i)
    {
        scanf("%d",&iMass);
        vecUnitMass.push_back(iMass);
    }
    
    int j=0;//单位质量 vecUnitMass[j]为第j+1类砝码的数量
    
    set<int> res;
    set<int> temp;
    int iNum;
    for(int i=0;i<iTypes;++i)
    {
        scanf("%d",&iNum);
        for(int k=0;k<iNum;++k)
        {
            temp.clear();
            if(res.empty()) temp={0,vecUnitMass[j]};
            else
            {
                for(auto & elem:res)
                {
                    temp.insert(elem+vecUnitMass[j]);
                }
            }
            res.insert(temp.begin(),temp.end());
        }
        ++j;
    }
    
    cout<<res.size()<<endl;
    
    return 0;
}

从单向链表中删除指定值的节点

#include <iostream>
#include <list>
using namespace std;
void Insert(list<int>& ls,int afterElem,int elem)
{
    list<int>::iterator it=ls.begin();
    while(it!=ls.end())
    {
        if(*it==afterElem)
        {
            ++it;
            if(it==ls.end())
            {
                ls.push_back(elem);
            }
            else{
                ls.insert(it, elem);
            }
            break;
        }
        ++it;
    }
}
int main()
{
    int iNodes;
    scanf("%d",&iNodes);
    
    list<int> lst;
    int after,elem;
    
    scanf("%d",&elem);
    lst.push_back(elem);//头结点
    
    --iNodes;
    while(iNodes-->0)
    {
        scanf("%d%d",& elem,& after);
        Insert(lst, after, elem);
    }
    
    int iToDel;
    scanf("%d",&iToDel);
    //删除所有等于iToDel的节点
    while(1)
    {
        list<int>::iterator it=lst.begin();
        while(1)
        {
            if(*it==iToDel)
            {
                list<int>::iterator itEnd=it;++itEnd;
                lst.erase(it, itEnd);
                break;
            }
            ++it;
            if(it==lst.end()) break;
        }
        if(it==lst.end()) break;
    }

    for(auto elem:lst) cout<<elem<<" ";
    cout<<endl;
    return 0;
}

挑7

#include <iostream>
#include <string>
using namespace std;
bool WithSevenBit(int num)
{
    int bit;
    while(num>0)
    {
        bit=num%10;
        if(bit==7) return true;
        
        num/=10;
    }
    return false;
}
int main()
{
    int n;
    scanf("%d",&n);
    int cnt=0;
    for(int i=7;i<=n;++i)
    {
        if( WithSevenBit(i) || i%7==0 ) ++cnt;
    }
    
    printf("%d\n",cnt);
    
    return 0;
}

高精度整数加法

#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> Add(vector<int>& vec1, vector<int>& vec2)
{
    //vec1,2都是逆序存储的 123 存的是 3 2 1
    int index=0;
    int k,bit;
    int next=0;
    vector<int> res;
    while(index<vec1.size()&&index<vec2.size())
    {
        k=vec1[index]+vec2[index]+next;
        bit=k%10;
        res.push_back(bit);
        next=k/10;
        
        ++index;
    }
    while(index<vec1.size()) 
    {
        k=vec1[index]+next;
        bit=k%10;
        res.push_back(bit);
        next=k/10;
        ++index;
    }
    while(index<vec2.size()) 
    {
        k=vec2[index]+next;
        bit=k%10;
        res.push_back(bit);
        next=k/10;
        ++index;
    }
    if(next!=0) res.push_back(next);
    return res;
}
int main()
{
    vector<int> vec1,vec2;
    
    string str;
    cin>>str;
    for(int i=str.size()-1;i>=0;--i) vec1.push_back(str[i]-'0');
    cin>>str;
    for(int i=str.size()-1;i>=0;--i) vec2.push_back(str[i]-'0');
    
    vector<int> res=Add(vec1,vec2);
    for(int i=res.size()-1;i>=0;--i)
    {
        cout<<res[i];
    }
    cout<<endl;
}

字符串中第一个只出现一次的字符

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<char> vec;
    char a;
    while(1)
    {
        scanf("%c",&a);
        
        if(a=='\n') 
        {
            break;
        }
        else{
            vec.push_back(a);
        }
    }
    
    int arr[26]={0};
    for(auto elem:vec)
    {
        ++arr[elem-'a'];
    }

    bool bFound=false;
    for(auto elem:vec)
    {
        if(arr[elem-'a']==1) 
        {
            printf("%c",elem);
            bFound=true;
            break;
        }
    }
    
    if(bFound==false) printf("%d",-1);
    
    
    return 0;
}

DNA序列

#include <iostream>
#include <string>
using namespace std;
int GCRatio(string str)
{
    int cnt=0;
    for(int i=0;i<str.size();++i)
    {
        if(str[i]=='G'||str[i]=='C') ++cnt;
    }
    return cnt;
}
int main()
{
    string str;
    int n;
    cin>>str>>n;

    int indexMaxGC=-1;
    int iGCRatio=0;
    string sub;
    for(int i=0;i<str.size()-n+1;++i)
    {
        sub=str.substr(i,n);
        if(GCRatio(sub)>iGCRatio)
        {
            indexMaxGC=i;
            iGCRatio=GCRatio(sub);
        }
    }
    
    cout<<str.substr(indexMaxGC,n)<<endl;
    return 0;
    
}

MP3光标位置

#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main()
{
    int n;
    scanf("%d",&n);
    
    vector<int> disk;
    int iSong;
    int pos;
    
    for(int i=1;i<=n;++i) disk.push_back(i);
    iSong=1;
    pos=1;//1 2 3 4
    
    string orders;
    cin>>orders;
    if(n<=4)
    {
        for(int i=0;i<orders.size();++i)
        {
            if(orders[i]=='U')
            {
                if(pos==1) pos=n;
                else --pos;
            }
            if(orders[i]=='D')
            {
                if(pos==n) pos=1;
                else ++pos;
            }
        }
        //输出
        for(int k=1;k<=n;++k) cout<<k<<" ";
        cout<<endl;
        cout<<pos<<endl;
        
    }
    else{//pos-鼠标在屏幕的位置 与 iSong-当前选中的歌曲 不同!
        for(int i=0;i<orders.size();++i)
        {
            if(orders[i]=='U')
            {
                if(pos==1)
                {
                    if(iSong==1)
                    {
                        iSong=n;pos=4;
                    }
                    else
                    {
                        --iSong;
                    }
                }
                else
                {
                    if(iSong==1)
                    {
                        iSong=n;
                        --pos;
                    }
                    else
                    {
                        --pos;
                        --iSong;
                    }
                }
            }
            if(orders[i]=='D')
            {
                if(pos==4)
                {
                    if(iSong==n)
                    {
                        iSong=1;pos=1;
                    }
                    else{
                        ++iSong;
                    }
                }
                else{
                    if(iSong==n)
                    {
                        iSong=1;++pos;
                    }
                    else{
                        ++pos;++iSong;
                    }
                }
            }
        }
        
        //输出 当前位置pos 当前歌曲 iSong
        int arr[5]={0};
        arr[pos]=iSong;
        int now=iSong;
        
        for(int i=pos-1;i>=1;--i)
        {
            --iSong;
            if(iSong==0) 
            {
                iSong=n;
            }
            arr[i]=iSong;
        }
        
        iSong=now;
        
        for(int i=pos+1;i<=4;++i)
        {
            ++iSong;
            if(iSong==n+1) 
            {
                iSong=1;
            }
            arr[i]=iSong;
        }
        
        for(int i=1;i<=4;++i)
        {
            cout<<arr[i]<<" ";
        }
        cout<<endl;
        cout<<now<<endl;
        
    }
    return 0;
}

矩阵乘法

#include <iostream>
using namespace std;
int main()
{
    int x,y,z;
    cin>>x>>y>>z;
    
    int a[100][100],b[100][100];
    int elem;
    for(int i=1;i<=x;++i)//x行
    {
        for(int  j=1;j<=y;++j)//y列
        {
            scanf("%d",&elem);
            a[i][j]=elem;
        }
    }
    
    for(int i=1;i<=y;++i)//y行
    {
        for(int  j=1;j<=z;++j)//z列
        {
            scanf("%d",&elem);
            b[i][j]=elem;
        }
    }
    
    //乘法
    int res[100][100];
    for(int i=1;i<=x;++i)//x行
    {
        for(int j=1;j<=z;++j)//z列
        {
            //res[i][j]为a数组 i行元素 与b数组 j列元素元素对应乘积之和
            for(int k=1;k<=y;++k)
            {
                res[i][j]+=a[i][k]*b[k][j];
            }
        }
    }
    
    //输出
    for(int i=1;i<=x;++i)//x行
    {
        for(int j=1;j<=z;++j)
        {
            cout<<res[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

字符串中连续最长的数字子串

#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
void test(string str)
{
    int longest=0;
    vector<string> subs;
    
    int start=0,end=0;
    for(int i=0;i<str.size();++i)
    {
        if(isdigit(str[i]))
        {
            start=i;
            end=i;
            while(isdigit(str[end])) ++end;
            if((end-start)>longest)
            {
                longest=end-start;
            }
            subs.push_back(str.substr(start,end-start));
            i=end-1;
        }
    }
    
    //最长的是longest
    for(int i=0;i<subs.size();++i)
    {
        if(subs[i].size()==longest)
        {
            cout<<subs[i];
        }
    }
    cout<<","<<longest<<endl;
}
int main()
{
    string str;
    while(cin>>str)
    {
        test(str);
    }
    return 0;
    
}

整数与IP地址的转换

要点

1. 数据范围,int 无法表示ip转化成的整数,这里用了long long,可以先考虑ip转换整数的最大值

2. copy不负责申请空间,直接就 copy 有问题

3. string 与 int 的相互转换

//C++11 引入了一些很方便的函数,比如:
to_string(...);
stoi(string);
#include <iostream>
#include <vector>
#include <math.h>
#include <string>
#include <algorithm>
using namespace std;
vector<int> DecToBin(int num)
{
    vector<int> res;
    int bit;
    for(int i=31;i>=0;--i)
    {
        bit=(num>>i)&1;
        res.push_back(bit);
    }
    return res;
}
long long BinToDec(vector<int> bits)
{
    long long res=0;
    int index=bits.size()-1;
    int power=0;
    for(;index>=0;--index)
    {
        res+=bits[index]*pow(2,power);
        ++power;
    }
    return res;
}
long long IpToNum(string str)
{
    vector<int> binbits;
    string sub;
    int temp;
    vector<int> bits;//
    
    int post=0;
    for(int i=0;i<str.size();++i)
    {
        post=i;
        while(str[post]!='.' && post<str.size())
        {
            ++post;
        }
        sub=str.substr(i,post-i);
        temp=stoi(sub);
        bits=DecToBin(temp);//32位
        bits.erase(bits.begin(), bits.begin()+24);
        
        //copy(bits.begin(),bits.end(),binbits.end()); 注意copy不负责申请空间
        for(auto elem:bits) binbits.push_back(elem);
       
        i=post;
    }
    return BinToDec(binbits);
}
string NumToIp(int num)
{
    vector<int> temp=DecToBin(num);
    vector<int> bits;

    //统一处理为32 bits
    if(temp.size()<32)
    {
        for(int i=0;i<32-temp.size();++i)
        {
            bits.push_back(0);
        }
    }
    for(auto elem:temp) bits.push_back(elem);

    vector<int> vec;
    string res;
    
    for(int i=0;i<bits.size();++i)
    {
        vec.push_back(bits[i]);
        if(vec.size()==8)
        {
            res+=to_string(BinToDec(vec));
            
            res+='.';
            vec.clear();
        }
    }
    //
    res.pop_back();
    return res;
}
int main()
{
    string ip,decNum;
    cin>>ip>>decNum;
    long num=stol(decNum);
    
    cout<<IpToNum(ip)<<endl;
    cout<<NumToIp(num)<<endl;
    return 0;
}

求解立方根(二分)

#include <iostream>
#include <iomanip>
using namespace std;
double GetCubeRoot(double num)
{
    //转换为正数
    double n=num;
    if(num<0) n=-num;
    
    double left=0,right=n;
    if(n<1) right=1;
        
    double mid,res;
    
    while(left<right)
    {
        mid=(left+right)/2.0;
        
        if(mid*mid*mid>n)
        {
            right=mid;
        }
        else{
            left=mid;
        }
        
        //达到精度
        if((right-left)<0.01) 
        {
//             res=((int)(right*100))/100.0;
            res=right;
            break;
        }
    }
    
    if(num<0) res=-res;
    return res;
}
int main()
{
    double num;
    while(cin>>num)
    {
        cout<<setiosflags(ios::fixed)<<setprecision(1)<<GetCubeRoot(num)<<endl;
    }
    return 0;
}

迷宫问题(递归)

一些说明

1. 地图从1开始,上到下为x轴正向,左到右为y轴正向

2. visited为标志下一个位置是否走过了,0 代表没走过,可以尝试 

#include <iostream>
#include <vector>
using namespace std;
vector<pair<int,int>> NextMove(int n, int m, int x, int y)
{
    vector<pair<int,int>> moves;
    //左上右下
    if(y>=2) moves.push_back(pair<int,int>(x,y-1));
    if(x>=2) moves.push_back(pair<int,int>(x-1,y));
    if(y<=m-1) moves.push_back(pair<int,int>(x,y+1));
    if(x<=n-1) moves.push_back(pair<int,int>(x+1,y));
    
    return moves;
}
//x,y为当前位置
bool FindPath(vector<vector<int>>& map,vector<pair<int,int>>& path, vector<vector<int>>& visited,int n, int m, int x, int y)
{
    if(x==n && y==m ) return true; 
    
    vector<pair<int,int>> Nexts=NextMove(n,m,x,y);
    bool WrongPath=true;
    
    for(auto elem:Nexts)
    {
        if( visited[elem.first][elem.second]==0
          && map[elem.first][elem.second]==0 )
        {
            WrongPath=false;
            {
                path.push_back(pair<int,int>(elem.first,elem.second));
                visited[elem.first][elem.second]=1;
            }
            bool res=FindPath(map, path, visited, n, m, elem.first, elem.second);
            if(res) return true;
//注意:别在这里加个什么else pop_back()
//将当前位置全尝试一遍再 pop_back()不迟!
        }
    }
    
    
    path.pop_back();
    return false;
}
int main()
{
    int n,m;//n行m列
    scanf("%d%d",&n,&m);
    vector<vector<int>> map;
    vector<int> vec;
    vector<pair<int,int> > path;
    
    //地图
    for(int i=0;i<=n;++i)
    {
        vec.clear();
        for(int j=0;j<=m;++j)
        {
            vec.push_back(0);
        }
        map.push_back(vec);
    }
    
    int elem;
    for(int i=1;i<=n;++i)//行数
    {
        for(int j=1;j<=m;++j)
        {
            scanf("%d",&elem);
            map[i][j]=elem;
        }
    }

    //访问标志位
    vec.clear();
    vector<vector<int>> visited;
    for(int i=0;i<=m;++i) vec.push_back(0);
    for(int i=0;i<=n;++i) visited.push_back(vec);
   
    path.push_back(pair<int,int>(1,1));
    visited[1][1]=1;
    
    bool res=FindPath(map,path,visited, n, m, 1, 1);
    if(res)
    {
        //输出路径
        for(auto elem:path)
        {
            cout<<"("<<elem.first-1<<","<<elem.second-1<<")"<<endl;
        }
    }
    
    return 0;
}

计算字符串的编辑距离(DP)

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
//     dp[i][j]表示 前i,j个字符的距离
    int dp[1010][1010];
    
    string strA,strB;
    cin>>strA>>strB;

    int lena=strA.size(),lenb=strB.size();
    int temp[3]={0};
    
    for(int i=1;i<=lena;++i) dp[i][0]=i;
    for(int i=1;i<=lenb;++i) dp[0][i]=i;
    
    for(int i=1;i<=lena;++i)
    {
        for(int j=1;j<=lenb;++j)
        {
            //注意 strA,B从0开始
            if(strA[i-1]==strB[j-1]) dp[i][j]=dp[i-1][j-1];//
            else{
                //第i,j个不同
                temp[0]=dp[i-1][j-1];//换A
                temp[1]=dp[i][j-1];//B插入A
                temp[2]=dp[i-1][j];//删除A
                sort(temp,temp+3);
                dp[i][j]=temp[0]+1;
            }
        }
    }
    
    printf("%d",dp[lena][lenb]);
    return 0;
}

trying to fully understand the dp transfer...

杨辉三角的变形

内存超限:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    //奇数+偶数=奇数
    int n;
    scanf("%d",&n);
    
    if(n==1 || n==2 ) 
    {
        printf("%d",-1);
        return 0;
    }
    
    vector<vector<int>> triangle;
    vector<int> vec;

    //row从1开始
    vec={-1};triangle.push_back(vec);
    //有效数据
    vec={1};triangle.push_back(vec);
    vec={1,1,1};triangle.push_back(vec);
    int elem;
    
    for(int row=3;row<=n;++row)
    {
        vec={1,row-1};
        for(int i=2;i<2*n-3;++i)
        {
            elem=triangle[row-1][i-2]+triangle[row-1][i-1]+triangle[row-1][i];
            vec.push_back(elem);
        }
        vec.push_back(row-1);
        vec.push_back(1);
        triangle.push_back(vec);
    }
    
    //第n行
    int index=1;
    for(int i=0;i<2*n-1;++i)
    {
        if(triangle[n][i]%2==0)
        {
            break;
        }
        
        ++index;
    }
    printf("%d",index);
    return 0;
    
}

找规律:前4个必然有偶数,具体证明可见于注释,说实话,也不知道这个结论到底对不对。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    //奇数+偶数=奇数
    int n;
    scanf("%d",&n);
    
    if(n==1 || n==2 ) 
    {
        printf("%d",-1);
        return 0;
    }
    
    int arr[5];
    arr[1]=1;
    arr[2]=n-1;
    //arr[3]从第三行开始 1+2 1+2+3 1+2+3+4 ... 1+2+3+...+n-1
    //i行[3]-(i-1)行[3] = i行[2],奇偶交替
    //假设前4个都是奇数,可以利用奇数+奇数=偶数,偶数+奇数=奇数 等性质 得到 [3]的差 并非奇数偶数交替的
    //所以前4个必有一个偶数
    arr[3]=1;
    for(int i=2;i<=n-1;++i)
    {
        arr[3]+=i;
    }

    bool Found=false;
    for(int i=1;i<=3;++i)
    {
        if(arr[i]%2==0)
        {
            Found=true;
            printf("%d",i);
            break;
        }
    }
    
    if(Found==false) printf("%d",4);
    
    return 0;
    
}

放苹果(递归)

参考:递归_牛客博客

#include <iostream>
using namespace std;
//arg1 arg2 都大于等于2
int f(int iApples,int iPlates)
{
    if(iApples<=1 || iPlates<=1 ) return 1;
    //至少有iPlates-iApples个盘子空的,可以不考虑
    if(iApples<iPlates) return f(iApples,iApples);
    //假设每个盘子都放了苹果,每个盘子里拿掉一个也等效
    //或者至少空一个盘子
    else{
        return f(iApples-iPlates,iPlates)+f(iApples,iPlates-1);
    }
}
int main()
{
    int iApples,iPlates;
    scanf("%d%d",&iApples,&iPlates);
    
    if(iApples<=1 || iPlates<=1) 
    {
        printf("%d",1);
        return 0;
    }
    
    int num=f(iApples,iPlates);
    printf("%d",num);
    
    
    return 0;
}

将真分数分解为埃及数

在网上copy的,https://www.cnblogs.com/repinkply/p/13406259.htmlhttps://www.cnblogs.com/repinkply/p/13406259.html不太懂:

#include<iostream>
#include<string>

using namespace std;

int main() 
{
    char ch='0';
    int a = 0;
    int b =0;

    while (cin >> a >> ch >> b)
    {
        while (a != 1) 
        {
            if (b % (a - 1) == 0) 
            {
                cout << 1 << "/" << b / (a - 1) << "+";
                a = 1;
            }
            else 
            {
                int c=0;
                c = b / a + 1;      //新的埃及分数的分母
                a = a - b % a;        //通分后相减得到的分子
                //因为:b=na+x,由通分可得分子为ac-b,c=n+1则分子为na+a-na-x=a-x,而x=b%a,所以分子为a-b%a
                b = b * c;            //通分后的分母
                cout << 1 << "/" << c << "+";
                if (b%a == 0) 
                {      //判断最新得到的是不是埃及分数
                    b = b / a;
                    a = 1;
                }
            }
        }

        cout << 1 << "/" << b << endl;
    }

    return 0;
}

之前写过一个大部分测试用例直接就超时了,只通过10%的用例。

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
// n/m (n<m) -> 
vector<pair<int,int>> Transfer(int n,int m)
{
    vector<pair<int,int>> res;
    // a/b + c/d = (ad+bc)/bd 不约分
    pair<int,int> num(1,2);
    pair<int,int> sum;
    while(1)
    {
        if(num.first*m<2*n)
        {
            sum.first=1;
            sum.second=num.second;
            break;
        }
        else{
            num.second+=1;
        }
    }
    //sum 已经有一个值了
    res.push_back(num);
    num.second+=1;
    
    while(1)
    {
        if( m*(sum.first*num.second+sum.second*num.first) <= n*sum.second*num.second )
        {
            res.push_back(num);
            sum.first=sum.first*num.second+sum.second*num.first;
            sum.second=sum.second*num.second;
            
            if( m*(sum.first*num.second+sum.second*num.first) == n*sum.second*num.second)
            {
                break;
            }
        }
//         else ( m*(sum.first*num.second+sum.second*num.first) > n*sum.second*num.second )
        else
        {
            num.second+=1;
        }
    }
    return res;
}
int main()
{
    int n,m;
    string str;
    vector<pair<int,int>> res;
    
    while(getline(cin,str))
    {
        int index=str.find("/");
        
//         cout<<"index"<<index<<endl;
//         cout<<str.substr(0,index)<<" "<<str.substr(index+1)<<endl;
        
        n=stoi(str.substr(0,index) );
        m=stoi(str.substr(index+1) );
        
        if(m%n==0)
        {
            cout<<1<<"/"<<(m/n)<<endl;
        }
        else{
            res=Transfer(n, m);
            for(int i=0;i<res.size();++i)
            {
                cout<<res[i].first<<"/"<<res[i].second;
                if(i!=res.size()-1)
                {
                    cout<<"+";
                }
            }
        }
    }
    
    return 0;
}

火车进站 (递归)

int 向 string的转换 to_string()

这个也是改了一会才通过,可见对递归还不够熟悉啊,重点在还原!

#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
bool Test(vector<string>& outs, string out, stack<int>& st, vector<int>& in,int iNow)//iNow仍未入栈的第一个元素
{
    if(out.size()==in.size()-1)
    {
        outs.push_back(out);
        return true;
    }
    
    if(st.size()==0)
    {
        //入栈
        if(iNow<in.size())
        {
            st.push(in[iNow]);
            ++iNow;
            Test(outs, out, st, in, iNow);
            st.pop();
            --iNow;
        }
    }
    else{
        //先出栈
        int elem=st.top();
        st.pop();
        out+=to_string(elem);
        Test(outs,  out, st, in, iNow);
        st.push(elem);
        out.erase(out.begin()+out.size()-1, out.end());
        
        
        //先压栈
        if(iNow<in.size())
        {
            st.push(in[iNow]);
            ++iNow;
            Test(outs,  out, st, in, iNow);
            --iNow;
            st.pop();
        }
    }
    
    return true;
}
int main()
{
    int n;
    scanf("%d",&n);
    
    vector<int> in;in.push_back(-1);
    int num;
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&num);
        in.push_back(num);
    }
    
    vector<string> outs;
    stack<int> st;
    string out;
    int iNow=1;
    
    Test(outs,  out, st, in, 1);
    
    sort(outs.begin(),outs.end());
    for(auto elem:outs)
    {
        for(auto train:elem)
        {
            cout<<train<<" ";
        }
        cout<<endl;
    }
    
    
    return 0;
}

配置文件恢复

1. 分割一个仅含空格的字符串函数

2. 匹配输入命令与合法命令行,不能用 str.find(input) != string::npos

必须要 str.find(input) == 0 ,表示从0 开始全部匹配。

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
vector<vector<string> > orders=
{
    {"reset"},
    {"reset","board"},
    {"board","add"},
    {"board","delete"},
    {"reboot","backplane"},
    {"backplane","abort"}
};
vector<string> Excution=
{
    {"reset what"},
    {"board fault"},
    {"where to add"},
    {"no board at all"},
    {"impossible"},
    {"install first"}
};
//空格分开
vector<string> SplitString(string str)
{
    vector<string> res;
    string sub;
    
    int i=0,pre=0;
    for(;i<str.size();++i)
    {
        while(str[i]==' ' && i<str.size() ) ++i;//找到非空格
        if(i==str.size())
        {
            sub=str.substr(pre,i-pre);
            res.push_back(sub);
            break;
        }
        
        pre=i;//pre指向一段有效串的首字符
        while(str[i]!=' ' && i<str.size() )++i;
        sub=str.substr(pre,i-pre);
        res.push_back(sub);
        
    }
    
    return res;
}

void ExcuteOrder(string str)
{
    vector<string> words=SplitString(str);
    
    if(words.size()==1)//只匹配一个关键字的命令行
    {
        if( orders[0][0].find(str)==0 )
        {
            cout<<"reset what"<<endl;
        }
        else{
            cout<<"unknown command"<<endl;
        }
    }
    else if(words.size()==2)
    {
        int cnt=0;
        int indexOrder=0;
        for(int i=0;i<orders.size();++i)
        {
            if(orders[i].size()==2)
            {
                if( orders[i][0].find(words[0]) ==0 
                  && orders[i][1].find(words[1]) ==0 )
                {
                    ++cnt;
                    indexOrder=i;
                }
            }
        }
        
        if(cnt==1)
        {
            cout<<Excution[indexOrder]<<endl;
        }
        else{
            cout<<"unknown command"<<endl;
        }
    }
    else{
        cout<<"unknown command"<<endl;
    }
    
}
int main()
{
    
    
    string str;
    while(getline(cin, str))
    {
        ExcuteOrder(str);
    }
    return 0;
}

参数解析

重点:与上一题(配置文件恢复)里的字符串分割一样的,不过是多个引号内合并的操作。

#include <iostream>
#include <vector>
#include <string>
#include <string.h>
using namespace std;
vector<string> SplitString(string str)
{
    vector<string> res;
    string sub;
    
    int i=0,pre=0;
    for(;i<str.size();++i)
    {
        while( str[i]==' ' && i<str.size() ) ++i;//找到非空格
        if(i==str.size())
        {
            sub=str.substr(pre,i-pre);
            res.push_back(sub);
            break;
        }
        
        if(str[i]=='"')//注意要去掉引号
        {
            pre=i;
            ++i;
            while(str[i]!='"' && i<str.size() )++i;
            ++i;
            sub=str.substr(pre+1,i-pre-2);
            res.push_back(sub);
        }
        else{
            pre=i;//pre指向一段有效串的首字符
            while(str[i]!=' ' && i<str.size() )++i;
            sub=str.substr(pre,i-pre);
            res.push_back(sub);
        }
    }
    
    return res;
}
int main()
{
    string str;
    vector<string> args;
    while(getline(cin,str))
    {
        args=SplitString(str);
        cout<<args.size()<<endl;
        for(auto elem:args)
        {
            cout<<elem<<endl;
        }
    }
}

合法IP

提交数次,有一些测试用例没有考虑完全。

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <cctype>
using namespace std;
bool LegalIP(string str)
{
    vector<int> nums;
    int num;
    string sub;
    
    if(str.find(' ')!=string::npos)
    {
        return false;
    }
    int pre=0;
    for(int i=0;i<str.size();++i)
    {
        pre=i;
        if( !isdigit (str[pre]) ) return false;
        
        while(str[i]!='.' && i<str.size() ) 
        {
            if(!isdigit(str[i])) return false;
            
            ++i;
        }
        
        sub=str.substr(pre,i-pre);
        if( sub.size()>1 && 
           stoi(sub.substr(0,1)) ==0 ) 
        {
            return false;
        }
        
        num=stoi(sub);
        if(num<0 || num>255 ) return false;
        nums.push_back(num);
    }
    
    if(nums.size()!=4) return false;
    
    return true;
}

int main()
{
    string str;
    getline(cin, str);
    bool res=LegalIP(str);
    if(res) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

字符串通配符(DP)

来自大佬的代码,仅仅就个人的理解加了一些注释,仍没有完全理解透彻,虽然大致看懂了别人的代码,但是让我独立写一个好像也有点问题。

大佬的文章

 注意:如果将i, j 循环中间的赋值删掉就会在部分测试用例下失败,

eg

str1 = *h 

str2 = h

v[i][0] = v[i-1][0]&&(s1[i-1]=='*')
#include <iostream>
#include <string>
#include <vector>
using namespace std;
 
// 判断字符是否符合要求
bool isOk(char c)
{
    return (isalpha(c)||isalnum(c)||c=='.');
}
 
bool Match(string s1,string s2)
{
    int m = s1.size();
    int n = s2.size();
    vector<vector<bool>> v(m+1,vector<bool>(n+1,false));
    v[0][0] = true;

    for(int i=1;i<=m;++i)
    {
        v[i][0] = v[i-1][0]&&(s1[i-1]=='*');//s1[i-1]即s1中第i个字符
        
        for(int j=1;j<=n;++j)
        {
            if(isOk(s1[i-1]) && 
               isOk(s2[j-1]) &&
               tolower(s1[i-1]) == tolower(s2[j-1]) )
                //匹配不分大小写
            {
                v[i][j]=v[i-1][j-1];
            }
            else if(s1[i-1] == '*')
                //只要第j个字符是合法的,s1里第i个通配符*就能完成i,j的匹配
            {
                if( isOk(s2[j-1]) )
                {
                    v[i][j]=v[i-1][j] || v[i][j-1];//*可以匹配0
                }
            }
            else if(s1[i-1] == '?')//s2第j个合法,s1第i个通配符?可以通配单个字符
            {
                if( isOk(s2[j-1]) )
                {
                    v[i][j] = v[i-1][j-1];
                }
            }
        }
    }
    return v[m][n];
}
int main(void)
{
    string s1,s2;
    while(cin>>s1>>s2)
    {
        if(Match(s1, s2)){
            cout << "true" << endl;
        }else{
            cout << "false" << endl;
        }
    }
    return 0;
}

DP之路漫漫啊...

Redraiment的走法 (DP)

最长严格递增子序列(不要求连续)

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    
    int num;
    vector<int> pillars;
    for(int i=0;i<n;++i)
    {
        scanf("%d",&num);
        pillars.push_back(num);
    }
    int dp[210];
    
    int res=0;
    for(int i=0;i<pillars.size();++i)
    {
        dp[i]=1;
        for(int j=0;j<i;++j)
        {
            if(pillars[j]<pillars[i])
            {
                dp[i]=max( dp[i],dp[j]+1);
            }
            res=max(dp[i],res);
        }
    }
    
    printf("%d",res);
    return 0;
}

表达式求值

调试了好一会儿,代码也比较乱啊,long way to go !

注意:负数与减号的区别,即 ' - ' 前无字符 或 前面字符为 ' ( ' 时为负数。

#include <iostream>
#include <stack>
#include <map>
#include <cctype>
using namespace std;
/*
        (    +    -    *    /    )
    (
    +
    -
    *
    /
    )
*/
map<char,int> mapOpertor;
int priorities[10][10];

//0 ()
//1 1优先级大 -1 1优先级小
int Priority(char operator1, char operator2)
{
    int i=mapOpertor[operator1];
    int j=mapOpertor[operator2];
    if(priorities[i][j]>0) return 1;
    else if(priorities[i][j]<0) return -1;
    else return 0;
}
void InitPriorityMap()
{
    char operators[6]={'(','+','-','*','/',')'};
    for(int i=0;i<6;++i)
    {
        mapOpertor[ operators[i] ]=i+1;
    }
    
    
    for(int i=1;i<=5;++i)    priorities[1][i]=-1;
    priorities[1][6]=0;
    
    priorities[2][1]=-1; priorities[2][2]=1; priorities[2][3]=1;
    priorities[2][4]=-1; priorities[2][5]=-1; priorities[2][6]=1;
    
    priorities[3][1]=-1; priorities[3][2]=1; priorities[3][3]=1;
    priorities[3][4]=-1; priorities[3][5]=-1; priorities[3][6]=1;
    
    priorities[4][1]=-1; priorities[4][2]=1; priorities[4][3]=1;
    priorities[4][4]=1; priorities[4][5]=1; priorities[4][6]=1;
    
    priorities[5][1]=-1; priorities[5][2]=1; priorities[5][3]=1;
    priorities[5][4]=1; priorities[5][5]=1; priorities[5][6]=1;
    
    priorities[6][1]=1; priorities[6][2]=1; priorities[6][3]=1;
    priorities[6][4]=1; priorities[6][5]=1; priorities[6][6]=1;
}

int Calc(int lhs,int rhs,char op)
{
    if(op=='+') return lhs+rhs;
    else if(op=='-') return lhs-rhs;
    else if(op=='*') return lhs*rhs;
    else if(op=='/') return lhs/rhs;
    
    return 0;
}
int main()
{
    InitPriorityMap();
    
    stack<char> stOperator;
    stack<int>  stOperand;
    char opFront;
    char opBack;
    int lhs,rhs,res;
    
    string str;
    getline(cin, str);
    
    for(int i=0;i<str.size();++i)
    {
        if(isdigit(str[i]))
        {
            int pre=i-1,ppre=i-2;
            if(str[pre] == '-'
              && ( ppre<0 || str[ppre]=='(' )
              )
            {
                stOperand.push(Calc(0, stoi(str.substr(i,1) ), str[pre] ));
                if(stOperator.top()=='-') stOperator.pop();
                continue;
            }
            //找到一个数字
            int iStart=i;
            while(isdigit(str[i]) ) ++i;
            string sub=str.substr(iStart,i-iStart);
            
            stOperand.push(stoi(sub));
            --i;
        }
        else{
            if(stOperand.size()==0
              || stOperator.size()==0
              ) 
            {
                stOperator.push(str[i]);
                continue;
            }
           
            
            opFront=stOperator.top();
            opBack=str[i];
            
            if(Priority(opFront, opBack)>0 )
            {
                lhs=stOperand.top();stOperand.pop();
                rhs=stOperand.top();stOperand.pop();
                res=Calc(rhs, lhs, opFront);
                
                stOperator.pop();
                stOperand.push(res);
                --i;  
            }else if(Priority(opFront, opBack)==0)
            {
                stOperator.pop();
            }
            else
            {
                stOperator.push(str[i]);
            }
            
        }
    }
    
    while( stOperator.size()!=0 )
    {
        if(stOperator.top()==')'
          || stOperator.top()=='(') stOperator.pop();
        
        opFront=stOperator.top(); stOperator.pop();
        
        lhs=stOperand.top();stOperand.pop();
        rhs=stOperand.top();stOperand.pop();
        
        res=Calc(rhs, lhs, opFront);
        
        stOperand.push(res);
        
    }
    
    res=stOperand.top();
    printf("%d\n",res);
    return 0;
}

四则运算

照搬表达式求值的代码,只是做了一个预处理:将表达式中的中括号与大括号改成小括号 (这个预处理似乎也是 有一点 glance at someone else's comment ,不过原本也准备这样试一下)

#include <iostream>
#include <stack>
#include <map>
#include <cctype>
using namespace std;
/*
        (    +    -    *    /    )
    (
    +
    -
    *
    /
    )
*/
map<char,int> mapOpertor;
int priorities[10][10];

//0 ()
//1 1优先级大 -1 1优先级小
int Priority(char operator1, char operator2)
{
    int i=mapOpertor[operator1];
    int j=mapOpertor[operator2];
    if(priorities[i][j]>0) return 1;
    else if(priorities[i][j]<0) return -1;
    else return 0;
}
void InitPriorityMap()
{
    char operators[6]={'(','+','-','*','/',')'};
    for(int i=0;i<6;++i)
    {
        mapOpertor[ operators[i] ]=i+1;
    }
    
    
    for(int i=1;i<=5;++i)    priorities[1][i]=-1;
    priorities[1][6]=0;
    
    priorities[2][1]=-1; priorities[2][2]=1; priorities[2][3]=1;
    priorities[2][4]=-1; priorities[2][5]=-1; priorities[2][6]=1;
    
    priorities[3][1]=-1; priorities[3][2]=1; priorities[3][3]=1;
    priorities[3][4]=-1; priorities[3][5]=-1; priorities[3][6]=1;
    
    priorities[4][1]=-1; priorities[4][2]=1; priorities[4][3]=1;
    priorities[4][4]=1; priorities[4][5]=1; priorities[4][6]=1;
    
    priorities[5][1]=-1; priorities[5][2]=1; priorities[5][3]=1;
    priorities[5][4]=1; priorities[5][5]=1; priorities[5][6]=1;
    
    priorities[6][1]=1; priorities[6][2]=1; priorities[6][3]=1;
    priorities[6][4]=1; priorities[6][5]=1; priorities[6][6]=1;
}

int Calc(int lhs,int rhs,char op)
{
    if(op=='+') return lhs+rhs;
    else if(op=='-') return lhs-rhs;
    else if(op=='*') return lhs*rhs;
    else if(op=='/') return lhs/rhs;
    
    return 0;
}
int main()
{
    InitPriorityMap();
    
    stack<char> stOperator;
    stack<int>  stOperand;
    char opFront;
    char opBack;
    int lhs,rhs,res;
    
    string str;
    getline(cin, str);
    
    for(int i=0;i<str.size();++i)
    {
        if(str[i]=='[') str[i]='(';
        if(str[i]==']') str[i]=')';
        if(str[i]=='{') str[i]='(';
        if(str[i]=='}') str[i]=')';
    }
    
    for(int i=0;i<str.size();++i)
    {
        if(isdigit(str[i]))
        {
            int pre=i-1,ppre=i-2;
            if(str[pre] == '-'
              && ( ppre<0 || str[ppre]=='(' )
              )
            {
                stOperand.push(Calc(0, stoi(str.substr(i,1) ), str[pre] ));
                if(stOperator.top()=='-') stOperator.pop();
                continue;
            }
            //找到一个数字
            int iStart=i;
            while(isdigit(str[i]) ) ++i;
            string sub=str.substr(iStart,i-iStart);
            
            stOperand.push(stoi(sub));
            --i;
        }
        else{
            if(stOperand.size()==0
              || stOperator.size()==0
              ) 
            {
                stOperator.push(str[i]);
                continue;
            }
           
            
            opFront=stOperator.top();
            opBack=str[i];
            
            if(Priority(opFront, opBack)>0 )
            {
                lhs=stOperand.top();stOperand.pop();
                rhs=stOperand.top();stOperand.pop();
                res=Calc(rhs, lhs, opFront);
                
                stOperator.pop();
                stOperand.push(res);
                --i;  
            }else if(Priority(opFront, opBack)==0)
            {
                stOperator.pop();
            }
            else
            {
                stOperator.push(str[i]);
            }
            
        }
    }
    
    while( stOperator.size()!=0 )
    {
        if(stOperator.top()==')'
          || stOperator.top()=='(') stOperator.pop();
        
        opFront=stOperator.top(); stOperator.pop();
        
        lhs=stOperand.top();stOperand.pop();
        rhs=stOperand.top();stOperand.pop();
        
        res=Calc(rhs, lhs, opFront);
        
        stOperand.push(res);
        
    }
    
    res=stOperand.top();
    printf("%d\n",res);
    return 0;
}

24点游戏(递归)

参考B站up Akarinnnn_​​​​​​    

的代码。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool Cal24(vector<double> nums)
{
    
    if(nums.size()==1)
    {
        if (abs (nums[0]-24)<0.00001) return true;
        else return false;
    }
    bool res=false;
    
    vector<double> vec;
    
    for(int i=0;i<nums.size();++i)
    {
        for(int j=0;j<nums.size();++j)
        {
            if(i==j) continue;
    
            vec.clear();
            for(int k=0;k<nums.size();++k)
            {
                if(k!=i && k!=j) vec.push_back(nums[k]);
            }
            
            double a=nums[i],b=nums[j];
            
            vec.push_back(a+b);
            if(Cal24(vec)) return true;
            vec.pop_back();
            
            vec.push_back(a-b);
            if(Cal24(vec)) return true;
            vec.pop_back();
            
            vec.push_back(b-a);
            if(Cal24(vec)) return true;
            vec.pop_back();
            
            
            vec.push_back(a*b);
            if(Cal24(vec)) return true;
            vec.pop_back();
            
            if(b!=0)
            {
                vec.push_back(a/b);
                if(Cal24(vec)) return true;
                vec.pop_back();
            }
            
        }
    }
    
    return false;
}
int main()
{
    int a,b,c,d;
    vector<double> vec;
    while(cin>>a>>b>>c>>d)
    {
        vec.clear();
       
        vec.push_back(a*1.0);
        vec.push_back(b*1.0);
        vec.push_back(c*1.0);
        vec.push_back(d*1.0);
        
        bool res=Cal24(vec);
        if(res) cout<<"true";
        else cout<<"false";
        
        cout<<endl;
    }
    return 0;
}

查找两个字符串a,b中的最大公共子串

直接暴力

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str1,str2;
    int iStart,iLength=-1;
    
    cin>>str1>>str2;
    if(str1.size()>str2.size())
    {
        string str=str2;
        str2=str1;
        str1=str;
    }
    
    //str1 是较小的串
    for(int i=0;i<str1.size();++i)
    {
        //各种长度
        for(int length=1;length<=str1.size()-i;++length)
        {
            string str=str1.substr(i,length);
            if( str2.find(str) != string::npos 
              && length>iLength )
            {
                iStart=i;
                iLength=length;
            }
        }
    }
    
    cout<<str1.substr(iStart,iLength)<<endl;
    return 0;
}

公共子串计算(动态规划)

可以用上面的暴力法,不过取iLength

或者DP:

注意,dp[i][j] 不是前 i 、j个字符组成子串的公共子串长度;而是 以i、j结尾的公共子串的长度,用另一个res 记录整个过程中的最大公共子串长度。

#include <iostream>
#include <string>
using namespace std;
int  dp[155][155];
// dp[i][j] - 公共子串的长度,str1中以第i个字符结尾;str2中以第j个字符结尾
//好好理解下!
int CommonSubStr(string str1,string str2)
{
    int len1=str1.size(),len2=str2.size();
    //init
    for(int i=1;i<=len1;++i) dp[i][0]=0;
    for(int i=1;i<=len2;++i) dp[0][i]=0;
    
    //
    int res=0;
    for(int i=1;i<=len1;++i)
    {
        for(int j=1;j<=len2;++j)
        {
            if(str1[i-1] == str2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
            
            res=res>dp[i][j]?res:dp[i][j];
        }
    }
    return res;
}
int main()
{
    string str1,str2;
    int iStart,iLength=0;
    
    cin>>str1>>str2;
    
    cout<<CommonSubStr(str1,  str2)<<endl;
    
    return 0;
}

密码截取(动态规划)

暴力法在部分案例超时

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

int main()
{
    string str;
    cin>>str;
    
    int iMax=1;
    int iLen=str.size();
    string half;
    string otherhalf;
    
    for(int i=0;i<str.size();++i)
    {
        //j表示右端下标
        
        //如果右边剩下偶数个字符
        if( (iLen-i)%2==0 )
        {
            for(int j=i;j<=(iLen-1+i)/2; ++j)
            {
                half=str.substr(i,j-i+1);
                otherhalf=half;
                reverse(otherhalf.begin(),otherhalf.end());
                
                //偶数对称
                if(str.find(otherhalf,j+1) == j+1)
                {
                    if((j-i+1)*2 > iMax)
                        iMax=(j-i+1)*2;
                }
                //奇数对称
                if(str.find(otherhalf,j+1) == j+2)//i与j
                {
                    if((j-i+1)*2+1 > iMax)
                        iMax=(j-i+1)*2+1;
                }
            }
            
        }
        else{//右边奇数个字符
            for(int j=i;j<=(iLen-1+i)/2-1; ++j)
            {
                half=str.substr(i,j-i+1);
                otherhalf=half;
                reverse(otherhalf.begin(),otherhalf.end());
                
                //偶数对称
                if(str.find(otherhalf,j+1) == j+1)
                {
                    if((j-i+1)*2 > iMax)
                        iMax=(j-i+1)*2;
                }
                //奇数对称
                if(str.find(otherhalf,j+1) == j+2)
                {
                    
                    if( (j-i+1)*2+1 > iMax)
                        iMax=(j-i+1)*2+1;
                }
            }
        }
    }
    
    cout<<iMax<<endl;
    return 0;
}

或者以单个字符中心扩散,遍历

或者DP

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
    string str;
    cin>>str;
    
    int iMax=1;
    int j;//子串右侧的下标
    
    bool dp[2520][2520]={false};
    for(int len=0;len<str.size();++len)
    {
        for(int i=0;i<str.size();++i)
        {
            j=i+len;
            if(j>=str.size()) break;
            
            if (0==len) dp[i][j]=true;
            else if (1==len)
            {
                if(str[i]==str[j]) dp[i][j]=true;
            }
            else{
                dp[i][j]=dp[i+1][j-1] && str[i]==str[j];
            }
            
            if(dp[i][j] && len+1>iMax) iMax=len+1;
        }
    }
   
    
    cout<<iMax<<endl;
    return 0;
}

合唱队(动态规划)

原理:

合唱队左侧是可能不连续的递增序列,右侧是可能不连续的递减序列,中间位符合这样的条件

正向以此结尾的递增序列长度L1,反向以此结尾的递减序列长度L2,在所有位中,中间位的 (L1+L2) 值最大。

注意:

1. 双向dp数组(正向、反向的最长递增子序列合并时dp数组也要reverse一下)

2. 双向合并时中间位计算了两次

3. reverse 的参数形式:左闭右开

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    vector<int> Height;
    int h;
    for(int i=0;i<n;++i)
    {
        scanf("%d",&h);
        Height.push_back(h);
    }
    
    int dp1[3010],dp2[3010];
    //
    for(int i=0;i<n;++i)
    {
        dp1[i]=1;
        for(int j=i-1;j>=0;--j)
        {
            if(Height[j] < Height[i] && dp1[i] < dp1[j]+1 ) dp1[i] = dp1[j]+1;
        }
    }
    
    reverse(Height.begin(),Height.end());
    
    for(int i=0;i<n;++i)
    {
        dp2[i]=1;
        for(int j=i-1;j>=0;--j)
        {
            if(Height[j] < Height[i] && dp2[i] < dp2[j]+1 ) dp2[i]= dp2[j]+1;
        }
    }
    
    reverse(dp2, dp2+n);
    
    int iMax=-1;
    for(int i=0;i<n;++i)
    {
        if(dp1[i]+dp2[i] > iMax) iMax=dp1[i]+dp2[i];
    }
    
    cout<<n-iMax+1<<endl;
    return 0;
}

购物单(动态规划)

参考网上的答案  原帖

 

 注意:moeny循环不能改成 for( j=1; j<=money; ++j )。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
    int iSatisfy=0;
    int money,num;
    scanf("%d%d",&money,&num);
    
    int* itemPri=new int[num+1]();
    int* itemImp=new int[num+1]();
    
    int* attach1Pri=new int[num+1]();
    int* attach1Imp=new int[num+1]();
    
    int* attach2Pri=new int[num+1]();
    int* attach2Imp=new int[num+1]();
    
    int v,p,q;
    for(int i=1;i<=num;++i)
    {
        scanf("%d%d%d",&v,&p,&q);
        v/=10;
        
        if(0==q)
        {
            itemPri[i]=v;
            itemImp[i]=v*p;
        }else if(0==attach1Pri[q]){
            //q主件所属的第一个附件没有取值
            attach1Pri[q]=v;
            attach1Imp[q]=v*p;
        }else{
            attach2Pri[q]=v;
            attach2Imp[q]=v*p;
        }
    }
    
 
    
    money/=10;
    int dp[32010];
    
    for(int i=1;i<=num;++i)
    {
        for(int j=money;j>=1;--j)
        {
            if(j>=itemPri[i]) dp[j] = max( dp[j], dp[j-itemPri[i]] + itemImp[i] );
            if(j>=itemPri[i]+attach1Pri[i]) dp[j] = max(dp[j], dp[ j-itemPri[i]-attach1Pri[i] ] + itemImp[i] + attach1Imp[i] );
            if(j>=itemPri[i]+attach2Pri[i]) dp[j] = max(dp[j], dp[ j-itemPri[i]-attach2Pri[i] ] + itemImp[i] + attach2Imp[i] );
            if(j>=itemPri[i]+attach1Pri[i]+attach2Pri[i]) 
                dp[j] = max(dp[j], dp[ j-itemPri[i]-attach1Pri[i]-attach2Pri[i] ] + itemImp[i] + attach1Imp[i] + attach2Imp[i] );
        }
    }
    
    cout<<dp[money]*10<<endl;
    return 0;
    
}

矩阵乘法计算量估算

这都能过

#include <iostream>
#include <vector>
#include <stack>
#include <string>
using namespace std;
// p*q q*r 计算量 p*q*r
stack<pair<int,int>> res;
int sum;
int iM=-1;
void Multi(pair<int,int> A, pair<int,int> B)
{
    pair<int,int> C;
    C.first=A.first;
    C.second=B.second;
    
    sum+=A.first*A.second*B.second;
    res.push(C);
}
void CalTime(vector<pair<int,int>>& matrixes,string str)
{
    for(int i=0;i<str.size();++i)
    {
        if(str[i]=='(') 
        {
            continue;

        }
        
        if(str[i]==')')
        {
            pair<int,int> rhs=res.top(); res.pop();
            pair<int,int> lhs=res.top(); res.pop();
            Multi(lhs, rhs);
        }
        
        if(str[i]>='A' && str[i]<='Z') 
        {
            ++iM;
            res.push(pair<int,int> ( matrixes[iM].first,matrixes[iM].second) );

        }
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    
    vector<pair<int,int>> matrixes;
    pair<int,int> elem;
    
    for(int i=0;i<n;++i)
    {
        scanf("%d%d",&elem.first,&elem.second);
        matrixes.push_back(elem);
    }
    
    
    
    string str;
    cin>>str;
    
    CalTime(matrixes, str);
    printf("%d\n",sum);
    return 0;
}

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值