华为机考108题(c++)(62-69)

本文探讨了多种编程问题的解决策略,包括位运算、字符串处理、动态规划和模拟等方法,展示了如何高效地处理各种计算任务。此外,还涉及了DNA序列分析、MP3播放器控制和24点游戏的算法实现。通过对这些挑战的深入分析,我们可以提升编程技能和问题解决能力。
摘要由CSDN通过智能技术生成

HJ62 查找输入整数二进制中1的个数

描述

输入一个正整数,计算它在二进制下的1的个数。

注意多组输入输出!!!!!!

数据范围: 1≤n≤231−1

输入描述:

输入一个整数

输出描述:

计算整数二进制中1的个数

解法一:运用位运算进行操作

#include <iostream>
using namespace std;

int n, res; // 定义我们输入的 n 和我们最后的二进制1的个数
void solve() {
    while(cin >> n) { // 多组输入我们的 n
        res = 0; // 因为是多组输入,我们把我们每次的答案都先清空为 0
        while(n) { // 如果 n 还有数字,不为0
            if (n & 1) res++; // 如果当前 n 的最后一位二进制位是 1, 答案加1
            n >>= 1; // n 向右移一次,将刚才计算过的二进制位剔除掉
        }
        cout << res << "\n"; // 输出最后的一个答案
    }
}
signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    solve();
    return 0;
}

解法二: STL容器

#include <iostream>
#include <bitset> // bitset在这个bitset的库里
using namespace std;

void solve() {
    int n;
    while(cin >> n) { // 多组输入一个n
        bitset<32> a = n; // 建立一个bitset,这个尖括号里面存的是位数,将n变成二进制存到a中
        cout << a.count() << "\n";  // 调用bitset的库函数输出二进制里面的1
    }
}
signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    solve();
    return 0;
}

方法三:转化二进制字符串

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

int main(){
    int n;
    while(cin >> n){
        int count = 0;
        string s = "";
        while(n){ //十进制转化成二进制
            s += ((n % 2) + '0'); //用字符串记录二进制每一位
            n /= 2;
        }
        for(int i = 0; i < s.length(); i++) //遍历字符串统计1的个数
            if(s[i] == '1')
                count++;
        cout<< count << endl;
    }
    return 0;
}

方法四:移位运算和位与运算

#include<iostream>
using namespace std;

int main(){
    int n;
    while(cin >> n){
        int count = 0;
        while(n){
            if(n & 1) //和最后一位按位与运算
                count++; //与的结果是1说明这位是1
            n >>= 1; //移位
        }
        cout<< count << endl;
    }
    return 0;
}

方法五:位与运算去掉二进制末尾1

#include<iostream>
using namespace std;

int main(){
    int n;
    while(cin >> n){
        int count = 0;
        while(n){
            count++; //统计+1
            n &= (n - 1); //去掉末尾的1
        }
        cout<< count << endl; //输出
    }
    return 0;
}

方法六:库函数 

#include<iostream>
#include<bitset>
using namespace std;

int main(){
    int n;
    while(cin >> n){
        bitset<32> bit(n); //转换32位二进制类
        cout << bit.count() << endl; //直接输出位数
    }
    return 0;
}

HJ63 DNA序列

描述

一个 DNA 序列由 A/C/G/T 四个字母的排列组合组成。 G 和 C 的比例(定义为 GC-Ratio )是序列中 G 和 C 两个字母的总的出现次数除以总的字母数目(也就是序列长度)。在基因工程中,这个比例非常重要。因为高的 GC-Ratio 可能是基因的起始点。

给定一个很长的 DNA 序列,以及限定的子串长度 N ,请帮助研究人员在给出的 DNA 序列中从左往右找出 GC-Ratio 最高且长度为 N 的第一个子串。

DNA序列为 ACGT 的子串有: ACG , CG , CGT 等等,但是没有 AGT , CT 等等

数据范围:字符串长度满足 1≤n≤1000  ,输入的字符串只包含 A/C/G/T 字母

输入描述:

输入一个string型基因序列,和int型子串的长度

输出描述:

找出GC比例最高的子串,如果有多个则输出第一个的子串

方法一:暴力解法

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

int main(){
    string s;
    int n;
    while(cin >> s >> n){
        int len = s.length();
        int resindex = 0, max = 0;
        for(int i = 0; i + n < len; i++){ //遍历字符串每一位,从该位开始
            int count = 0;
            for(int j = 0; j < n; j++){ //从i位起长为n的字符串
                if(s[i + j] == 'G' || s[i + j] == 'C') //统计CG出现次数
                    count++; 
            }
            if(count > max){ //取次数更多的
                resindex = i; //得到序列起始下标
                max = count;
            }
        }
        cout << s.substr(resindex, n) << endl; //根据下标和n输出
    }
    return 0;
}

方法二:滑动窗口

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

int main(){
    string s;
    int n;
    while(cin >> s >> n){
        int len = s.length();
        int resindex = 0, max = 0;
        int count = 0;
        for(int i = 0; i < n; i++) //录入最前面的窗口
            if(s[i] == 'C' || s[i] == 'G')
                count++;
        max = count; //录下第一个窗口的CG数量作为最大
        int left = 1, right = n; //从录入窗口的左右点右移一位开始
        while(right < len){ //直到右窗口结束
            if(s[left - 1] == 'C' || s[left - 1] == 'G') //窗口左边出去的是CG
                count--;
            if(s[right] == 'C' || s[right] == 'G') //窗口右边进来的是CG
                count++;
            if(count > max){ //更新,取最大值
                max = count;
                resindex = left;
            }
            left++;
            right++;
        }
        cout << s.substr(resindex, n) << endl; //根据下标和n输出
    }
    return 0;
}

 HJ64 MP3光标位置

描述

MP3 Player因为屏幕较小,显示歌曲列表的时候每屏只能显示几首歌曲,用户要通过上下键才能浏览所有的歌曲。为了简化处理,假设每屏只能显示4首歌曲,光标初始的位置为第1首歌。

现在要实现通过上下键控制光标移动来浏览歌曲列表,控制逻辑如下:

  1. 歌曲总数<=4的时候,不需要翻页,只是挪动光标位置。

光标在第一首歌曲上时,按Up键光标挪到最后一首歌曲;光标在最后一首歌曲时,按Down键光标挪到第一首歌曲。

其他情况下用户按Up键,光标挪到上一首歌曲;用户按Down键,光标挪到下一首歌曲。

2. 歌曲总数大于4的时候(以一共有10首歌为例):

特殊翻页:屏幕显示的是第一页(即显示第1 – 4首)时,光标在第一首歌曲上,用户按Up键后,屏幕要显示最后一页(即显示第7-10首歌),同时光标放到最后一首歌上。同样的,屏幕显示最后一页时,光标在最后一首歌曲上,用户按Down键,屏幕要显示第一页,光标挪到第一首歌上。

一般翻页:屏幕显示的不是第一页时,光标在当前屏幕显示的第一首歌曲时,用户按Up键后,屏幕从当前歌曲的上一首开始显示,光标也挪到上一首歌曲。光标当前屏幕的最后一首歌时的Down键处理也类似。

其他情况,不用翻页,只是挪动光标就行。

数据范围:命令长度1≤s≤100 ,歌曲数量1≤n≤150 

进阶:时间复杂度:O(n) ,空间复杂度:O(n) 

输入描述:

输入说明:
1 输入歌曲数量
2 输入命令 U或者D

输出描述:

输出说明
1 输出当前列表
2 输出当前选中歌曲

方法一:模拟

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

int main(){
    int n;
    string commands;
    while(cin >> n >> commands){
        int num = 1;
        // first:当前屏幕显示页的第一首歌曲的编号
        int first = 1;
        // 歌曲总数不超过4时,不需翻页
        if(n <= 4) {
            for(int i = 0; i < commands.size(); i++){
                // 特殊向上翻页
                if(num == 1 && commands[i] == 'U'){
                    num = n; 
                // 特殊向下翻页
                }else if(num == n && commands[i] == 'D'){
                    num = 1;
                }else if(commands[i] == 'U'){
                    num--;
                }else{
                    num++; 
                }
            }
            for(int i = 1; i <= n - 1; i++){//输出当前页
                cout << i << ' ';
            }
            cout << n << endl << num << endl;
        }else{// 歌曲总数大于4时,需要翻页
            for(int i = 0; i < commands.size(); i++){
                // 特殊向上翻页
                if(num == 1 && commands[i] == 'U') {
                    first = n-3;
                    num = n;
                }else if(num == n && commands[i] == 'D') {// 特殊向下翻页
                    first = 1;
                    num = 1;
                }else if(num == first && commands[i] == 'U')//一般向上翻页
                {
                    first--;
                    num--;
                }else if(num == first + 3 && commands[i] == 'D')//一般向下翻页
                {
                    first++;
                    num++;
                }else if(commands[i] == 'U'){//其他情况,不翻页,只移动光标
                    num--;
                }else{
                    num++;
                }
            }
            for(int i = first; i < first + 3; i++){//输出当前页面
                cout << i << ' ';
            }
            cout << first + 3 << endl << num << endl;
        }
    }
    return 0;
}


方法二:滑动窗口

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main(){
    int n;
    string commands;
    while(cin >> n >> commands){
        int num = 1;//选中的歌曲
        int win_b = 1;//页面的起始
        int win_e = min(4,n);//页面的末位置
        for(int i = 0; i < commands.size(); i++){
            if(commands[i] == 'U') {//向上移动一格
                num = (num-1-1+n)%n + 1;
            }else if(commands[i] == 'D') {//向下移动一格
                num = num % n + 1;
            }
            if(num < win_b){//如果当前歌曲在窗口前,则将窗口往前移动
                win_b = num;
                win_e = win_b + 3;
            }else if(num > win_e){//如果当前歌曲在窗口后,则将窗口往后移动
                win_e = num;
                win_b = win_e - 3;
            }
        }
        for(int i = win_b; i <= win_e; i++){//输出当前页面
            cout << i << ' ';
        }
        cout << endl;
        cout << num << endl;//输出选中的歌曲
    }
    return 0;
}


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

描述

查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。

注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!

数据范围:字符串长度1≤length≤300 

进阶:时间复杂度:O(n^3) ,空间复杂度:O(n) 

输入描述:

输入两个字符串

输出描述:

返回重复出现的字符

方法一:暴力枚举

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

int main(){
    string s1, s2;
    while(cin >> s1 >> s2){
        if(s1.length() > s2.length()) //使较小的字符串在前
            swap(s1, s2);
        string output = "";
        for(int i = 0; i < s1.length(); i++){ //遍历s1每个起始点的每个长度
            for(int j = i; j < s1.length(); j++){
                if(int(s2.find(s1.substr(i, j - i + 1))) < 0) //截取子串能够在s2中被找到
                    break;
                else if(output.length() < j - i + 1) //更新较长的子串
                    output = s1.substr(i, j - i + 1);
            }
        }
        cout << output << endl;
    }
    return 0;
}

方法二:枚举改进

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

int main(){
    string s1, s2;
    while(cin >> s1 >> s2){
        if(s1.length() > s2.length()) //使较小的字符串在前
            swap(s1, s2);
        string output = "";
        for(int i = 0; i < s1.length(); i++){ //遍历s1每个起始点
            for(int j = 0; j < s2.length(); j++){ //遍历s2每个起点
                int length = 0;
                int x = i, y = j;
                while(x < s1.length() && y < s2.length() && s1[x] == s2[y]){ //比较每个起点为始的子串
                    x++;
                    y++;
                    length++;
                }
                if(output.length() < length) //更新更大的长度子串
                    output = s1.substr(i, x - i);
            }
        }
        cout << output << endl;
    }
    return 0;
}

方法三:动态规划

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

int main(){
    string s1, s2;
    while(cin >> s1 >> s2){
        if(s1.length() > s2.length()) //使较小的字符串在前
            swap(s1, s2);
        vector<vector<int> > dp(s1.length() + 1, vector<int>(s2.length() + 1, 0)); //dp[i][j]表示到s1第i个个到s2第j个为止的公共子串长度
        int max = 0, end = 0;
        for(int i = 1; i <= s1.length(); i++){
            for(int j = 1; j <= s2.length(); j++){
                if(s1[i - 1] == s2[j - 1]) //如果该两位相同
                    dp[i][j] = dp[i - 1][j - 1] + 1; //则增加长度
                else //否则
                    dp[i][j] = 0; //该位置为0
                if(dp[i][j] > max){ //更新最大长度
                    max = dp[i][j];
                    end = i - 1;
                }
            }
        }
        cout << s1.substr(end - max + 1, max) << endl; //输出最长子串
    }
    return 0;
}

HJ66 配置文件恢复

描述

有6条配置命令,它们执行的结果分别是:

命   令执   行
resetreset what
reset boardboard fault
board addwhere to add
board deleteno board at all
reboot backplaneimpossible
backplane abortinstall first
he heunknown command

注意:he he不是命令。

为了简化输入,方便用户,以“最短唯一匹配原则”匹配(注:需从首字母开始进行匹配):

1、若只输入一字串,则只匹配一个关键字的命令行。例如输入:r,根据该规则,匹配命令reset,执行结果为:reset what;输入:res,根据该规则,匹配命令reset,执行结果为:reset what;
2、若只输入一字串,但匹配命令有两个关键字,则匹配失败。例如输入:reb,可以找到命令reboot backpalne,但是该命令有两个关键词,所有匹配失败,执行结果为:unknown command

3、若输入两字串,则先匹配第一关键字,如果有匹配,继续匹配第二关键字,如果仍不唯一,匹配失败。

例如输入:r b,找到匹配命令reset board 和 reboot backplane,执行结果为:unknown command。

例如输入:b a,无法确定是命令board add还是backplane abort,匹配失败。

4、若输入两字串,则先匹配第一关键字,如果有匹配,继续匹配第二关键字,如果唯一,匹配成功。例如输入:bo a,确定是命令board add,匹配成功。
5、若输入两字串,第一关键字匹配成功,则匹配第二关键字,若无匹配,失败。例如输入:b addr,无法匹配到相应的命令,所以执行结果为:unknow command。
6、若匹配失败,打印“unknown command”

注意:有多组输入。

数据范围:数据组数:1≤t≤800 ,字符串长度1≤s≤20 

进阶:时间复杂度:O(n) ,空间复杂度:O(n)\O(n) 

输入描述:

多行字符串,每行字符串一条命令

输出描述:

执行结果,每条命令输出一行

方法一:模拟存储

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(){
    vector<pair<string, string>> cmdin = { { "reset","" } ,{ "reset","board" } ,{ "board","add" } ,{ "board","delete" } ,{ "reboot","backplane" } ,{ "backplane","abort" } };
    vector<string> cmdout = { "reset what" ,"board fault" ,"where to add" ,"no board at all" ,"impossible" ,"install first" };
    string s;
    while (getline(cin,s)){
        string s1 , s2;
        int pos = 0;
        //以空格为分界划分
        while (pos < s.size() && s[pos] != ' '){//遍历一遍找到空格的位置
            pos++;
        }
        s1 = s.substr(0, pos);
        if (pos != s.size()){
            s2 = s.substr(pos + 1, s.size());
        }
		int count1 = 0, count2 = 0;
		string result;
		for (auto iter=cmdin.begin();iter!=cmdin.end();iter++){
			int flag1 = iter->first.find(s1) == 0? 1 : 0;//判断第一个关键字是否匹配
			int flag2;
			if (s2 != "") {
				flag2 = iter->second.find(s2) == 0? 1 : 0;//判断第二个关键字是否匹配
			}else if(s2==""&&iter->second==""){//如果没有第二个关键字,默认匹配成功
				flag2 = 1;
			}else{
                flag2 = 0;
            }
			if (flag1 && flag2)//两个关键字都匹配上了
			{
				count1++;
				count2++;
				result = cmdout[iter - cmdin.begin()];
			}
		}
		if (count1 == 1 && count2 == 1){//两个关键字都匹配成功,且只有一组匹配
			cout << result << endl;
		}else {//匹配失败或有多组匹配
			cout << "unknown command" << endl;
		}
	}
	return 0;
}

方法二: 正则表达式

#include <iostream>
#include <string>
#include <regex>
#include <vector>

using namespace std;

int main(){
    vector<pair<string, string>> cmdin = { { "reset","" } ,{ "reset","board" } ,{ "board","add" } ,{ "board","delete" } ,{ "reboot","backplane" } ,{ "backplane","abort" } };
    vector<string> cmdout = { "reset what" ,"board fault" ,"where to add" ,"no board at all" ,"impossible" ,"install first" };
    string s;
    while (getline(cin,s)){
        string s1 , s2;
        int pos = 0;
        //以空格为分界划分
        while (pos < s.size() && s[pos] != ' '){//遍历一遍找到空格的位置
            pos++;
        }
        s1 = s.substr(0, pos);
        if (pos != s.size()){
            s2 = s.substr(pos + 1, s.size());
        }
		int count1 = 0, count2 = 0;
		string result;
		for (auto iter=cmdin.begin();iter!=cmdin.end();iter++){
            string pattern1 = s1 + "[a-z]*";//正则表达式
            int flag1 = regex_match(iter->first, regex(pattern1));//第一个关键字匹配
            string pattern2 = s2 + "[a-z]*";//正则表达式
            int flag2 = 0;
            if((s2 == "" && iter->second == "")){
                flag2 = 1;
            }else if(s2 != ""){
                flag2 = regex_match(iter->second, regex(pattern2));//第二个关键字匹配
            }
            if (flag1 && flag2)//两个关键字都匹配上了
			{
				count1++;
				count2++;
				result = cmdout[iter - cmdin.begin()];
			}
		}
		if (count1 == 1 && count2 == 1){//两个关键字都匹配成功,且只有一组匹配
			cout << result << endl;
		}else {//匹配失败或有多组匹配
			cout << "unknown command" << endl;
		}
	}
	return 0;
}

HJ67 24点游戏算法

描述

给出4个1-10的数字,通过加减乘除运算,得到数字为24就算胜利,除法指实数除法运算,运算符仅允许出现在两个数字之间,本题对数字选取顺序无要求,但每个数字仅允许使用一次,且需考虑括号运算

此题允许数字重复,如3 3 4 4为合法输入,此输入一共有两个3,但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。

输入描述:

读入4个[1,10]的整数,数字允许重复,测试用例保证无异常数字。

输出描述:

对于每组案例,输出一行表示能否得到24点,能输出true,不能输出false

方法一:穷举遍历

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

double cal(double a, double b, char c){ //根据运算符运算结果
    switch(c){
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': return a / b;
    }
    return 0;
}

bool check(vector<double>& nums){
    char op[4] = {'+', '-', '*', '/'};
    sort(nums.begin(), nums.end()); //先按照从小到大排
    do{
          for(int i = 0; i < 4; i++) //遍历三个位置的所有可能运算符
              for(int j = 0; j < 4; j++)
                  for(int k = 0; k < 4; k++){
                      double first = cal(nums[0], nums[1], op[i]); //依次运算
                      double second = cal(first, nums[2], op[j]);
                      if(cal(second, nums[3], op[k]) == 24) //判断是否等于24
                          return true;
                  }
      }while(next_permutation(nums.begin(), nums.end())); //依次找到其他排列
    return false;
}

int main(){
    vector<double> nums(4); 
    while(cin >> nums[0] >> nums[1] >> nums[2] >> nums[3]){ //输入4个数字
        if(check(nums))
            cout << "true" << endl;
        else
            cout << "false" << endl;
    }
    return 0;
}

方法二:递归搜索

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

bool check(vector<double> nums, double result){ //递归检查能否组成24
    if(nums.empty()) //数组为空,判断等不等于24
        return result == 24;
    for(int i = 0; i < nums.size(); i++){ //遍历剩下的数字
        vector<double> rest(nums);
        rest.erase(rest.begin() + i); //删去使用的数字
        if(check(rest, result + nums[i]) //分别 进行加减乘除4种运算
          || check(rest, result - nums[i])
          || check(rest, result * nums[i])
          || check(rest, result / nums[i]))
            return true;
    }
    return false;
}

int main(){
    vector<double> nums(4); 
    while(cin >> nums[0] >> nums[1] >> nums[2] >> nums[3]){ //输入4个数字
        if(check(nums, 0))
            cout << "true" << endl;
        else
            cout << "false" << endl;
    }
    return 0;
}

 HJ68 成绩排序

描述

给定一些同学的信息(名字,成绩)序列,请你将他们的信息按照成绩从高到低或从低到高的排列,相同成绩

都按先录入排列在前的规则处理。

例示:
jack      70
peter     96
Tom       70
smith     67

从高到低  成绩
peter     96
jack      70
Tom       70
smith     67

从低到高

smith     67

jack      70

Tom       70

peter     96

注:0代表从高到低,1代表从低到高

数据范围:人数:1≤n≤200 

进阶:时间复杂度:O(nlogn) ,空间复杂度:O(n) 

输入描述:

第一行输入要排序的人的个数n,第二行输入一个整数表示排序的方式,之后n行分别输入他们的名字和成绩,以一个空格隔开

输出描述:

按照指定方式输出名字和成绩,名字和成绩之间以一个空格隔开

方法一:库函数

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

bool cmp0(const pair<string, int>& a, const pair<string, int>& b) { //重载降序比较
    return a.second > b.second;
}
 
bool cmp1(const pair<string, int>& a, const pair<string, int>& b) { //重载升序比较
    return a.second < b.second;
}
int main()
{
    int n, flag;
    while (cin >> n >> flag) { 
        vector<pair<string, int>> record(n); //记录名字和成绩
        for (int i = 0; i < n; i++) { //输入成绩
            string name;
            int grade;
            cin >> name;
            cin>> grade;
            record[i].first = name;
            record[i].second = grade;
        }
        if (flag == 0) { //根据flag决定升序还是降序
            stable_sort(record.begin(), record.end(), cmp0);
        }
        else {
            stable_sort(record.begin(), record.end(), cmp1);
        }      
        for (int i = 0; i < n; i++) { //输出
            cout << record[i].first << ' ' << record[i].second << endl;
        }
    }
    return 0;
}

方法二:桶排序

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

int main()
{
    int n, flag;
    while (cin >> n >> flag) { 
        vector<string> score[101]; // 准备0-100分的桶
        for(int i = 0; i < n; i++){ //输入n个数据
            string name;
            int grade;
            cin >> name >> grade;
            score[grade].push_back(name); //将相应分数后面加入名字
        }
        if(flag == 0){ //降序
            for(int i = 100; i >= 0; i--){ //从100开始依次输出每个名字和分数
                for(int j = 0; j < score[i].size(); j++)
                    cout << score[i][j] << " " << i << endl;
            }
        }else{ //升序
            for(int i = 0; i <= 100; i++){ //从0开始依次输出每个名字和分数
                for(int j = 0; j < score[i].size(); j++)
                    cout << score[i][j] << " " << i << endl;
            }
        }
    }
    return 0;
}

HJ69 矩阵乘法

 

输入描述:

第一行包含一个正整数x,代表第一个矩阵的行数
第二行包含一个正整数y,代表第一个矩阵的列数和第二个矩阵的行数
第三行包含一个正整数z,代表第二个矩阵的列数
之后x行,每行y个整数,代表第一个矩阵的值
之后y行,每行z个整数,代表第二个矩阵的值

输出描述:

对于每组输入数据,输出x行,每行z个整数,代表两个矩阵相乘的结果

方法一:

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int x, y, z;
    while (cin >> x >> y >> z){
        vector<vector<int>> A(x, vector<int>(y, 0));
        vector<vector<int>> B(y, vector<int>(z, 0));
        vector<vector<int>> C(x, vector<int>(z, 0));
        for(int i = 0; i < x; ++i){//输入矩阵A
            for(int j = 0; j < y; ++j)
                cin >> A[i][j];
        }
        for(int i = 0; i < y; ++i){//输入矩阵B
            for(int j = 0; j < z; ++j)
                cin >> B[i][j];
        }
        for(int i = 0; i < x; ++i){//计算C[i][j]的值
            for(int j = 0; j < z; ++j)
                for(int k = 0; k < y; ++k)//A的第i行和B的第j列相乘的结果为C[i][j]
                    C[i][j] += A[i][k] * B[k][j];
        }
        for(int i = 0; i < x; ++i){//输出C
            for(int j = 0; j < z-1; ++j)
                cout << C[i][j] << " ";
            cout << C[i][z-1] << endl;
        }
    }
    return 0;
}

方法二:

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int x, y, z;
    while (cin >> x >> y >> z){
        vector<vector<int>> A(x, vector<int>(y, 0));
        vector<vector<int>> B(y, vector<int>(z, 0));
        vector<vector<int>> C(x, vector<int>(z, 0));
        for(int i = 0; i < x; ++i){//输入矩阵A
            for(int j = 0; j < y; ++j)
                cin >> A[i][j];
        }
        for(int i = 0; i < y; ++i){//输入矩阵B
            for(int j = 0; j < z; ++j)
                cin >> B[i][j];
        }
        for(int i = 0; i < x; ++i){
            for(int j = 0; j < y; ++j){
                for(int k = 0; k < z; ++k){//计算C第i行的值
                    C[i][k] += A[i][j] * B[j][k];
                }
            }
        }
        for(int i = 0; i < x; ++i){//输出C
            for(int j = 0; j < z-1; ++j)
                cout << C[i][j] << " ";
            cout << C[i][z-1] << endl;
        }
    }
    return 0;
}

方法三:暴力法

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

int main(){
    int x, y, z;
    while(cin >> x >> y >> z){
        vector<vector<int> > A(x, vector<int>(y, 0));
        vector<vector<int> > B(y, vector<int>(z, 0));
        for(int i = 0; i < x; i++) //输入两个矩阵
            for(int j = 0; j < y; j++)
                cin >> A[i][j];
        for(int i = 0; i < y; i++)
            for(int j = 0; j < z; j++)
                cin >> B[i][j];
        vector<vector<int> > C(x, vector<int>(z, 0)); //构建结果矩阵
        for(int i = 0; i < x; i++) //遍历相乘相加
            for(int j = 0; j < y; j++)
                for(int k = 0; k < z; k++)
                    C[i][k] += A[i][j] * B[j][k]; //行*列相加
        for(int i = 0; i < x; i++){ //输出
            for(int j = 0; j < z; j++)
                cout << C[i][j] << " ";
            cout << endl;
        }
    }
    return 0;
}

方法四:暴力法缓存优化

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

int main(){
    int x, y, z;
    while(cin >> x >> y >> z){
        vector<vector<int> > A(x, vector<int>(y, 0));
        vector<vector<int> > B(y, vector<int>(z, 0));
        for(int i = 0; i < x; i++) //输入两个矩阵
            for(int j = 0; j < y; j++)
                cin >> A[i][j];
        for(int i = 0; i < y; i++)
            for(int j = 0; j < z; j++)
                cin >> B[i][j];
        vector<vector<int> > C(x, vector<int>(z, 0)); //构建结果矩阵
        int temp;
        for(int i = 0; i < x; i++)
            for(int k = 0; k < y; k++){
                temp = A[i][k];  //优先访问这个元素
                for(int j = 0; j < z; j++)
                    C[i][j] += temp * B[k][j]; //行*列相加,这一行访问不中断
            }
        for(int i = 0; i < x; i++){ //输出
            for(int j = 0; j < z; j++)
                cout << C[i][j] << " ";
            cout << endl;
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南叔先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值