華爲機試訓練做題總結(三)

54. 挑7

題目描述 :
輸出7有關數字的個數,包括7的倍數,還有包含7的數字(如17,27,37…70,71,72,73…)的個數

思路分析:
這個問題有一個很好的解決辦法就是將數字轉爲字符型,然後查找看字符裏面有沒有的符合條件的 字符 ,然後再判斷是否數字能否整除7
代碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    while(cin>>n){
        //分爲兩個存在7倍數  和 數字裏有7的數字
        int count=0;
        string s;
        int res=0;
        for(int i=7;i<=n;i++){
            stringstream ss;
            ss<<i;
            ss>>s;
            if(s.find('7')!=s.npos || i%7 ==0){
                count++;
            }
        } 
        cout<<count<<endl;
    }
    return 0;
}

或者

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    while(cin>>n){
        int cnt=0;
        for(int i=7;i<=n;i++){
            int temp=i;
            if(i%7==0){
                cnt++;
            }else{
                while(temp!=0){
                    if(temp%10==7)
                    {
                        ++cnt;
                        break;
                    }
                    temp=temp/10;
                }
            }

        }
        cout<<cnt<<endl;
    }
    return 0;
}

55. INOC產品部完全數計算

題目描述 :
完全數(Perfect number),又稱完美數或完備數,是一些特殊的自然數。

它所有的真因子(即除了自身以外的約數)的和(即因子函數),恰好等於它本身。

例如:28,它有約數1、2、4、7、14、28,除去它本身28外,其餘5個數相加,1+2+4+7+14=28。

給定函數count(int n),用於計算n以內(含n)完全數的個數。計算範圍, 0 < n <= 500000

返回n以內完全數的個數。 異常情況返回-1

思路分析:
這個計算還是比較簡單,但是我感覺我的方法應該不是計算速度最快的。主要思想就是遍歷計算。
代碼:

#include<bits/stdc++.h>
using namespace std;
bool perfect_num(int n){
    vector<int>sv;
    for(int i=1;i<n;i++){
        if(n%i==0)
        {
            sv.push_back(i);
        }

    }
    int sum=0;
    for(int i=0;i<sv.size();i++){
        sum+=sv[i];
    }
    if(sum==n)
        return true;
    else 
        return false;
}
int main(){
    int n;
    while(cin>>n){
        int count=0;
        for(int i=1;i<=n;i++){
            if(perfect_num(i))
                count++;
        }
        cout<<count<<endl;
    }
    return 0;
}

更加優化的計算方式:
#include<bits/stdc++.h>
using namespace std;
bool is_perfect_num(int i){
    int sum=0;
    int j=1;
    int t=i/2;
    while(j<t){
        if(i%j==0){
            sum+=j;
            if(j!=1){
                t=i/j;
                if(j!=i/j)
                    sum+=i/j;
            }
        }
        ++j;
        if(sum>i)
            return false;
    }
    return (sum==i)?true:false;
}
int count_perfect_num(int n){
    if(n<=0 || n>500000) return -1;
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(is_perfect_num(i))
            ++cnt;
    }
    return cnt;
}

int main(){
    int range;
    while(cin>>range){
        cout<<count_perfect_num(range)<<endl;
    }
    return 0;
}

56. 高精度整數加法

題目描述 :
在計算機中,由於處理器位寬限制,只能處理有限精度的十進制整數加減法,比如在32位寬處理器計算機中,
參與運算的操作數和結果必須在-231~231-1之間。如果需要進行更大範圍的十進制整數加法,需要使用特殊
的方式實現,比如使用字符串保存操作數和結果,採取逐位運算的方式。如下:
9876543210 + 1234567890 = ?
讓字符串 num1=”9876543210”,字符串 num2=”1234567890”,結果保存在字符串 result = “11111111100”。
-9876543210 + (-1234567890) = ?
讓字符串 num1=”-9876543210”,字符串 num2=”-1234567890”,結果保存在字符串 result = “-11111111100”。

思路分析:
這個題目就是通過
代碼:

#include <iostream>
#include <algorithm>
#include <sstream>
using namespace std;
int strComp(string &s1, string &s2)//返回0,表示len1>len2
{
    int len1 = s1.length();
    int len2 = s2.length();
    if (len1>len2)
        return 0;
    else if (len1<len2)
        return 1;
    else
    {
        if (s1 >= s2)
            return 0;
        else
            return 1;
    }
}
string itos(long long tmp)
{
    stringstream ss;
    ss << tmp;
    string s1 = ss.str();
    return s1;
}

string add1(string numStr1, string numStr2) //兩個都是正
{
    string res;
    int c = 0, temp;
    if (numStr1.size() != numStr2.size())
    {                                           //長度不同先補零
        while (numStr1.size() < numStr2.size())
        {
            numStr1.insert(0, 1, '0');
        }
        while (numStr1.size() > numStr2.size())
        {
            numStr2.insert(0, 1, '0');  //在0下標元素前面插一個0
        }
    }

    for (int i = numStr1.size() - 1; i >= 0; i--)
    {                                                    //按位相加,從低位開始
        temp = (numStr1[i] - '0') + (numStr2[i] - '0') + c;
        if (temp>9)
        {
            temp = temp % 10;
            c = 1;        
        }
        else
            c = 0;
        res += itos(temp);
    }
    if (c == 1)  res += '1';//最高位還有進位,則補1個'1'
    reverse(res.begin(), res.end());//逆置字符串後結果就是相加後的值(res是從低位往裏添加字符的)
    return res;
}




string add2(string numStr1, string numStr2) //兩個都是負
{
    string res;
    int c = 0, temp;
    if (numStr1.size() != numStr2.size())
    {                                           //長度不同先補零
        while (numStr1.size() < numStr2.size())
        {
            numStr1.insert(1, 1, '0');
        }
        while (numStr1.size() > numStr2.size())
        {
            numStr2.insert(1, 1, '0');  //在1下標元素前面插一個0
        }
    }
    for (int i = numStr1.size() - 1; i>0; i--)
    {                                                  //最高位不管
        temp = (numStr1[i] - '0') + (numStr2[i] - '0') + c;
        if (temp>9)
        {
            temp = temp % 10;
            c = 1;
        }
        else
            c = 0;
        res += itos(temp);
    }
    if (c)res += '1';//最高位
    res += '-';      //添加'-'
    reverse(res.begin(), res.end());
    return res;
}

string add3(string numStr1, string numStr2) //一正一負
{
    string res;
    int flag = 0;
    int c = 0, temp;
    string a, b;//a-b a是被減數 b是減數 帶負號的給減數
    if (numStr1[0] == '-') { b = numStr1; a = numStr2; }
    else{ b = numStr2; a = numStr1; }
    b = b.substr(1);
    if (a.size() != b.size())
    {                                           //長度不同先補零
        while (a.size() < b.size())
        {
            a.insert(0, 1, '0');
        }
        while (a.size() > b.size())
        {
            b.insert(0, 1, '0');  //在0下標元素前面插一個0
        }
    }
    if (strComp(a, b) == 1)
    {
        string t = b;
        b = a;
        a = t;
        flag = 1;
    }

    for (int i = a.size() - 1; i>=0; i--)
    {                                                  //最高位不管
        temp = (a[i] - '0')-(b[i] - '0')-c;
        if (temp<0)
        {
            temp =temp+10;
            c = 1;
        }
        else
            c = 0;
        res += itos(temp);
    }
    if(flag==1)res += '-';      //添加'-'
    reverse(res.begin(), res.end());
    return res;
}

int main()
{
    string numStr1, numStr2;
    while (cin >> numStr1 >> numStr2)
    {
        string result;
        if (numStr1[0] != '-'&&numStr2[0] != '-') result = add1(numStr1, numStr2);
        else if (numStr1[0] == '-'&&numStr2[0] == '-') result = add2(numStr1, numStr2);
        else result = add3(numStr1, numStr2);
        cout << result << endl;
    }
    system("pause");
    return 0;
}

57. 輸入n個整數,輸出其中最小的k個

題目描述 :
輸入說明
1 輸入兩個整數 (一個是數組的大小,一個是輸出數組的大小)
2 輸入一個整數數組
輸出一個整數數組

思路分析:
這個題目問題,其實思路不難,你先排序,然後在把最小的幾個數字給輸出出來就行了。但是由於我基本功還不夠紮實,然後在一些細節上栽了跟頭,一個就是vector容器不需要自己造輪子寫swap函數,還有一個就是你用swap函數的時候,不需要在意是否取了指針放進去,直接用vector的數組就可以了。還有一個就是在排序的時候出現了一些問題,感覺很尷尬,要好好努力。

代碼:

#include<bits/stdc++.h>
using namespace std;
int RandomInRange(int start,int end){
    if(end>start){
        srand(time(NULL));
        return start+rand()%((end-start)); //產生start ~end 之間的隨機數
    }
    return 0;
}
void swap(int* a,int* b){
    int temp=*a;
    *a=*b;
    *b=temp;
}

int partion(vector<int>& numbers,int start,int end,int length ){
    if(numbers.empty() || start<0 ||end >=length || length<=0)
        exit(0);
    int index=RandomInRange(start,end);
    swap(&numbers[index],&numbers[end]);
    int small=start-1;
    for(index=start;index<end;++index){
        if(numbers[index]<numbers[end]){
            ++small;
            if(small!=index){
                swap(&numbers[index],&numbers[small]);
            }
        }
    }
    ++small;
    swap(&numbers[small],&numbers[end]);
    return small;
}

void quic_sort(vector<int>& numbers,int start,int end,int length){
    if(start==end)
        return;
    int index=partion(numbers,start,end,length);
    if(index>start)
        quic_sort(numbers,start,index-1,length);
    if(index<end)
        quic_sort(numbers,index+1,end,length);

}

int main(){
    int num,result_num;
    while(cin>>num>>result_num){
        vector<int>numbers;
        int temp;
        for(int i=0;i<num;i++)
        {
            cin>>temp;
            numbers.push_back(temp);
        }
        quic_sort(numbers,0,num-1,num);
        for(int i=0;i<result_num-1;i++)
        {
            cout<<numbers[i]<<" ";
        }
        cout<<numbers[result_num-1]<<endl;
    }
    return 0;
}

58. 找出字符串第一個只出現一次的字符

題目描述 :
輸入說明
輸入一個非空字符串
輸出第一個只出現一次的字符,如果不存在輸出-1

思路分析:
這個題目沒想到特別好的方法,當時腦子裏面只有一個想法就是用stack,因爲,如果進來一個字母,然後發現前面的字母和自己一樣就消失,這樣就可以完美解決問題,但是自己還是太年輕。這樣會導致一個問題就是,如果奇數個字母會出現錯誤(假設不論這個stack是否能實現)。然後我偷看了牛客上其他人的解答,有一個很不錯的解答思路,就是 用find函數和rfind 函數,因爲find函數,是從正面找字符,然後返回字母的位置,而rfind函數是找到字母最後出現的位置。因此只要 這兩者一樣就能解決問題。

代碼:

#include<bits/stdc++.h>
using namespace std;

int main(){
    string str;
    while(cin>>str){
        int i;
        for( i=0;i<str.length();i++){
            if(str.find(str[i])==str.rfind(str[i])){
                cout<<str[i]<<endl;
                break;
            }
        }
         if(i==str.length())
               cout<<-1<<endl; 
    }
    return 0;
}

59. 放蘋果

題目描述 :
題目描述
把M個同樣的蘋果放在N個同樣的盤子裏,允許有的盤子空着不放,問共有多少種不同的分法?(用K表示)5,1,1和1,5,1 是同一種分法。
輸入
每個用例包含二個整數M和N。0<=m<=10,1<=n<=10。

思路分析:
這個題目應用遞歸可以很方便的解答。主要就是將分蘋果,按照兩個情況來,一個就是存在空盤子,還有一個就是沒有空盤子。
還有一個需要注意的地方就是,沒有蘋果的時候,也是一種分法。

代碼:

#include<bits/stdc++.h>
using namespace std;
//有盤子
int put_apple(int m,int n){
    if(m<0)
        return 0;
    if(m==1 || n==1 || m==0)
        return 1;
    return put_apple(m,n-1)+put_apple(m-n,n);
}
int main(){
    int n,m;
    while(cin>>m>>n){
        cout<<put_apple(m,n)<<endl;
    }
    return 0;
}

60. 查找輸入整數二進制中1的個數

題目描述 :
輸入一個整數
計算整數二進制中1的個數

思路分析:
這一題在劍指offer中有,基本思想就是數字向右移,並和1相與 不爲0 就加1

代碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    while(cin>>n){
        int counter=0;
        while(n){
        if(n&0x1)
        {
            counter++;
        }
            n=n>>1;
        }
        cout<<counter<<endl;
    }
    return 0;
}

61. DNA序列

題目描述 :
輸入一個string型基因序列,和int型子串的長度
找出GC比例最高的子串,如果有多個輸出第一個的子串
思路分析:
開始的時候基本思路沒錯,後面想 複雜了,其實就是你一個個地遍歷過去,然後,比照前面的比例,如果後面的比例大於之前的,你就覆蓋之前的。開始的時候我整了一個>=簡直愚蠢,還整了一個deque進行存儲,完全沒有必要,用str.substr()完全夠用。

代碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    string str;
    int n;
    while(cin>>str>>n){
      int max=0;  
      int index=0;
        for(int i=0;i<str.length()-n;i++){
            string son_str=str.substr(i,i+n);
            int counter=0;
            for(int j=0;j<n;j++){
                if(son_str[j]=='C' || son_str[j]=='G')
                    counter++;
            }
            if(max<counter){
                index=i;
                max=counter;
            }
        }
        cout<<str.substr(index,n)<<endl;
    }
    return 0;
}

62. MP3光標位置

題目描述 :
輸入:
輸入說明:
1 輸入歌曲數量
2 輸入命令 U或者D
輸出:
1 輸出當前列表
2 輸出當前選中歌曲
思路分析:
這一題學到的一個東西scanf("%d",&n)成功輸入多少個變量就返回多少值。經常可以這麼用while (scanf("%d", &n) == 1)
這道題最重要的就是細緻分析每一個情況。

代碼:

/* 維護當前屏幕上,頂端歌曲名稱cur_head,指針偏置位移0<=cur_pos<4 */
#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

string s;

int main() {
    int n;
    while (scanf("%d", &n) == 1) {
        cin >> s;
        int cur_head = 1, cur_pos = 0;
        if (n <= 4) {
            for (int i = 0; i < (int)s.size(); i++) {
                if (s[i] == 'U') {
                    cur_pos = (cur_pos + n - 1) % n;
                } else {
                    cur_pos = (cur_pos + 1) % n;
                }
            }
        } else {
            for (int i = 0; i < (int)s.size(); i++) {
                if (s[i] == 'U'){
                    if(cur_head == 1 && cur_pos == 0){
                        cur_head = n - 3;
                        cur_pos = 3;
                    }else{
                        if(cur_pos > 0){
                            cur_pos--;
                        }else{
                            cur_head--;
                        }
                    }
                }else{
                    if(cur_head == n - 3 && cur_pos == 3){
                        cur_head = 1;
                        cur_pos = 0;
                    } else {
                        if(cur_pos < 3){
                            cur_pos++;
                        } else {
                            cur_head++;
                        }
                    }
                }
            }
        }
        for (int i = 0; i < min(n, 4); i++) {
            if (i) {
                printf(" ");
            }
            printf("%d", cur_head + i);
        }
        printf("\n%d\n", cur_head + cur_pos);
    }
    return 0;
}

63. 查找兩個字符串a,b中的最大公共子串

題目描述 :
輸入:
輸入說明:
輸入兩個字符串
輸出:
返回重複出現的字符
思路分析:
這一題,其實不難,但是我當時卡了,到最後冷靜理清了一下思路,問題還是解決了,說明我的底子還是薄。當時問題出在了兩個地方,一個就是for(int i=stand_len;i>0 && str_result==" ";i--) 我當時沒有用&& str_result==" "這個語句的作用就是相當於判斷,最大的子串是否已經被賦值了。
還有一個就是continue;這個是最精髓的,如果之前的子串不符合要求,就繼續找下一個子串。而我之前在這個位置用的break;導致了問題的出現。

代碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    string str1,str2;
    while(cin>>str1>>str2){
        int stand_len=min(str1.length(),str2.length());
        if(str1.length()>str2.length())
            swap(str1,str2);
        string str_result=" ";
        for(int i=stand_len;i>0 && str_result==" ";i--){
            for(int j=0;j<stand_len-i ;j++){
                 string str_temp=str1.substr(j,i);
                 if(int(str2.find(str_temp))<0)
                     continue;
                 str_result=str_temp; 
                   break;
            }
        }
        cout<<str_result<<endl;
    }
    return 0;
}

64. 配置文件恢復

題目描述 :
輸入:
輸入說明:
多行字符串,每行字符串一條命令
輸出:
執行結果,每條命令輸出一行
思路分析:

**這道題,思路不難,但是這道題卡了一段時間,主要是一些小細節沒有注意好。一個就是find函數找不到指定字符時,不是返回-1,而是返回一個很大的數。另一個就是輸入字符串存在空格,就不能用cin了,而是需要用getline(cin,str)。還有一個就是子串記得要多加一個1,作爲最後位置的“\0”。
這個題的思路還是很簡單的,一個就是,子串的劃分,還有一個就是map類型的應用**

代碼:

#include<bits/stdc++.h>
using namespace std;
//建立一個字典,將相應的指令存進去
map<string,string> config_map(){
    map<string,string>config;
    config.insert(pair<string,string>("reset","reset what"));
    config.insert(pair<string,string>("reset board","board fault"));
    config.insert(pair<string,string>("board add","where to add"));
    config.insert(pair<string,string>("board delet","no board at all"));
    config.insert(pair<string,string>("reboot backplane","impossible"));
    config.insert(pair<string,string>("backplane abort","install first"));
    config.insert(pair<string,string>("he he","unkown command"));
    return config;
}
//建立一個將帶有空格的字符串拆分成兩個字符串的函數
vector<string> split_str(string & str){
    vector<string>input_str;
        if(str.find(" ")>0 && str.find(" ")<100 ){
            input_str.push_back(str.substr(0,str.find(" ")+1));
            input_str.push_back(str.substr(str.find(" ")+1,str.size()-str.find(" ")+1));                    
        }else{
            input_str.push_back(str);
        }
    return input_str;
}
//匹配的子串函數
bool son_str(string str1,string str2){
    if(str2.find(str1)==0)
        return true;
    return false;
}
//進行匹配的函數
bool match_string( string str1,string str2){
    vector<string> split_str1=split_str(str1);
    vector<string> split_str2=split_str(str2);
    //將兩個字符串拆分成兩個部分,先對比第一個字符,如果第一個字符匹配了,然後就不看第二個匹配了
    //優先對比首字母,然後向後面進行對比
        for(int i=0;i<split_str1.size();i++){
            if(!son_str(split_str1[i],split_str2[i]))
                return false; 
            else
                continue;
    }
    return true;
}
//封裝一下match_string函數
void match_file(string str){
    map<string,string> map_list=config_map();
    map<string,string>::iterator iter;
    for(iter=map_list.begin();iter!=map_list.end();iter++){

        if(match_string(str,iter->first)){
            cout<<iter->second<<endl;
            return;
        }
    }   
    cout<<map_list["he he"]<<endl; 
    return;
}
int main(){
    string str;
    while(getline(cin, str)){
        match_file(str);
    }
    return 0;
}

65. 24點遊戲算法

題目描述 :
問題描述:給出4個1-10的數字,通過加減乘除,得到數字爲24就算勝利
輸入:
4個1-10的數字。[數字允許重複,但每個數字僅允許使用一次,測試用例保證無異常數字]
輸出:
true or false

思路分析:
這個問題我開始沒整明白怎麼做,但是大體方向是對的,就是用遞歸。
解決辦法就是將數字和計算的符號分別進行遞歸排序
將24加減乘除依次減少到最前面的數字,並且和最前面的數字相等,然後就找到了最終的結果
代碼:

#include<bits/stdc++.h>
using namespace std;
//inline C++的關鍵字 在函數
/*
    申明或定義中函數返回類型前加上關鍵字inline 就可以將函數指定爲內斂函數 

    關鍵字必須和函數定義放在才能讓函數稱爲內聯
    內聯函數可以調試 ,同時消除max寫成函數的額外執行開銷
*/
inline void Swap(int &a ,int &b){
    int temp =a;
    a =b;
    b=temp;
}
bool is24(int a[],int begin,int end ,double tot){
    if(begin==end-1)
        return (a[begin]==tot);
    else{
        bool ans =false;
        for(int i=begin;i<end;i++){
            swap(a[i],a[end-1]);
            ans = ans || is24(a, begin, end - 1, tot + a[end - 1]) || is24(a, begin, end - 1, tot - a[end - 1]) || is24(a, begin, end - 1, tot * a[end - 1]) || is24(a, begin, end - 1, tot / a[end - 1]);
            swap(a[i],a[end-1]);
        }
        return ans;
    }
}
int main(){
  int a[4];
    while(cin>>a[0]>>a[1]>>a[2]>>a[3]){
        if(is24(a,0,4,24))
            cout<<"true"<<endl;
        else
            cout<<"false"<<endl;
    }

    return 0;
}

66. 成績排序

題目描述 :
輸入多行,先輸入要排序的人的個數,然後分別輸入他們的名字和成績,以一個空格隔開
按照指定方式輸出名字和成績,名字和成績之間以一個空格隔開
實例:
輸入:
3
0
fang 90
yang 50
ning 70
輸出:
fang 90
ning 70
yang 50
思路分析:
這個問題用的是sort和stable_sort,以及結構體進行排序,還是基本的東西不熟啊
上面兩個函數都是用的快排,時間複雜度在所有排序中最低,爲O(nlog2n)
sort的應用:
1. 兩個參數
sort(a,a+N),其中a是數組,a+N 表示對a[0]至a[N-1]的N個數進行排序,默認從小到大。
2. 傳入三個參數
sort(a,a+N,cmp),第三個參數是一個函數(bool類型的函數);如果讓函數從大到小排序,可以用如下的算法實現:
bool cmp(int a,int b){return a>b;}
sort(a,a+N,cmp);//一般用vec.begin() vec.end()
stable_sort的用法和sort一致(區別就是stable_sort函數遇到兩個數相等時,不對其交換順序

代碼:

#include<bits/stdc++.h>
using namespace std;
struct student{
    string name;
    int grade;
};
bool cmp0(const student &stu1,const student & stu2){
    return stu1.grade>stu2.grade;
}
bool cmp1(const student &stu1,const student & stu2){
    return stu1.grade<stu2.grade;
}
int main(){
   int x=0;
   int num=0;
   while(cin>>num>>x){
       vector<student>stu(num);
       for(int i=0;i<num;++i){
           cin>>stu[i].name>>stu[i].grade;
       }
       if(x==0){
           stable_sort(stu.begin(),stu.end(),cmp0);
       }else{
           stable_sort(stu.begin(),stu.end(),cmp1);
       }
       for(int i=0;i<num;i++){
           cout<<stu[i].name<<" "<<stu[i].grade<<endl;
       }
   } 
    return 0;
}

67. 矩陣乘法

題目描述 :
如果A是個x行y列的矩陣,B是個y行z列的矩陣,把A和B相乘,其結果將是另一個x行z列的矩陣C。這個矩陣的每個元素是由下面的公式決定的:
原型:
voidmatrix_multiply(int *m1,int *m2,int *r, int x, int y, int z);
輸入參數:
int *m1:x行y列的矩陣(array1[x][y])

int *m2:y行z列的矩陣(array2[y][z])

int x:矩陣m1的行數

int y:矩陣m1的列數/矩陣m2的行數

int z:矩陣m2的列數

輸出參數:
int *r:矩陣m1, m2相乘的結果(array3[x][z])
返回值:
void
思路分析:
這一題不難 ,然後還是錯了,而且還是0%的準確率 但是在自己的IDE上運行沒有問題,很痛苦,典型的華爲題目。

這一題學到了如何用vector構造二維數組vector<vector<int>>matrix(row,vector<int>(col,0)) row行col列的零數組。
同時求matrix的列數,matrix.at(0).size()
代碼:

#include<bits/stdc++.h>
using namespace std;
int matrix_res(vector<vector<int>> &matrix1, vector<vector<int>> &matrix2, int row, int col) {
    int res = 0;
    for (int i = 0; i < matrix1.at(0).size(); i++) {
        //cout << "行:" << matrix1[row][i]<<"列:"<< matrix2[i][col];
        res += matrix1[row][i] * matrix2[i][col];
    }
    return res;
}
int main() {
    int row1 = 0, col1 = 0;
    int row2 = 0, col2 = 0;
    while (cin >> row1 >> col1 >> row2 >> col2) {
        vector<vector<int>>matrix1(row1, vector<int>(col1, 0));
        vector<vector<int>>matrix2(row2, vector<int>(col2, 0));
        for (int i = 0; i < row1; i++) {
            for (int j = 0; j < col1; j++) {
                cin >> matrix1[i][j];
            }
        }
        for (int i = 0; i < row2; i++) {
            for (int j = 0; j < col2; j++) {
                cin >> matrix2[i][j];
            }
        }
        vector<vector<int>>res(row1, vector<int>(col2, 0));
        for (int i = 0; i < row1; i++) {
            for (int j = 0; j < col2; j++) {
                res[i][j] = matrix_res(matrix1, matrix2, i, j);
            }
        }
        for (int i = 0; i < row1; i++) {
            for (int j = 0; j < col2; j++) {
                cout << res[i][j] << " ";
            }
            cout << endl;
        }
    }

    return 0;
}

68. 矩陣乘法計算量估算

題目描述 :
矩陣乘法的運算量與矩陣乘法的順序強相關。
例如:
A是一個50×10的矩陣,B是10×20的矩陣,C是20×5的矩陣
計算A*B*C有兩種順序:((AB)C)或者(A(BC)),前者需要計算15000次乘法,後者只需要3500次。
輸入參數:
3
50 10
10 20
20 5
(A(BC))
輸出參數:
3500

思路分析:
這一題真的很有意思,兩個問題當時卡住了我,一個是這個怎麼估算,還有一個是怎麼根據給出的法則算出。
解決辦法:
1. 就是直接算,//腦子秀逗了 ,基本的乘法次數都矇蔽了,直接就是A(m,n)* B(n,k)兩個矩陣得到m*k的矩陣,運算次數爲m*n*k,C(q,m) *(A(m,n)* B(n,k)),則運算次數爲q*m*k+m*n*k,
2. 這個就是用棧,當輸入的是字母不彈出,如果是‘)’ 就需要彈出相關的值,同時還需要注意彈出的同時改變相關的數值,因此需要用引用將相關的數值直接改變(具體看代碼,簡直秀的頭皮發麻)
代碼:

#include<bits/stdc++.h>
using namespace std;
//腦子秀逗了 ,基本的乘法次數都矇蔽了,直接就是A(m,n)* B(n,k)兩個矩陣得到m*k的矩陣,運算次數爲m*n*k,C(q,m) *(A(m,n)* B(n,k)),則運算次數爲q*m*k+m*n*k,
int main(){
    int n;
    string s;
    while(cin>>n){
       vector<vector<int>>a(n,vector<int>(2,0));
       for(int i=0;i<n;i++){
           for(int j=0;j<2;j++){
               cin>>a[i][j];
           }
       }
        cin>>s;
        //自己做相關的壓棧彈出的
        int sum=0;
        stack<char> cal;
        int count=0;
        for(int i=0;i<s.size();i++){
            if(s[i]==')')
            {
                if(cal.size()!=1){
                    vector<int>temp2 = a[cal.top()-'A'];
                    cal.pop();
                    vector<int>& temp1 =a[cal.top()-'A'];
                    //這個地方用引用 temp1的改變 將直接改變cal.top()的值,非常秀
                    count += temp1[1]*temp1[0]*temp2[1];
                    temp1[1]=temp2[1];
                }
            }else if(s[i]!='(')
                cal.push(s[i]);
        }
        cout<<count<<endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章