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首歌。
现在要实现通过上下键控制光标移动来浏览歌曲列表,控制逻辑如下:
-
歌曲总数<=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条配置命令,它们执行的结果分别是:
命 令 | 执 行 |
reset | reset what |
reset board | board fault |
board add | where to add |
board delete | no board at all |
reboot backplane | impossible |
backplane abort | install first |
he he | unknown 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;
}