P7184 [CRCI2008-2009] MAJSTOR 多层循环的遍历
#include <iostream>
using namespace std;
#include <string>
#include <algorithm>
#include <vector>
int getScore(char Sven,char Friend){
if(Sven == 'S' && Friend == 'P') return 2;
if(Sven == Friend) return 1;
if(Sven == 'P' && Friend == 'R') return 2;
if(Sven == 'R' && Friend == 'S') return 2;
return 0;
}
int main(){
int r;
cin>>r;
string sven;
cin>>sven;//输入Sven的手势
int n;
cin>>n;
vector<string> friends(n);
for(auto & Friend :friends) cin>>Friend;//输入朋友的手势
//计算实际得分
int actualScore =0;
for(int i = 0;i < r;i++){//遍历每轮的手势
for(int j = 0;j<n;j++){//遍历每个朋友的第i轮手势
actualScore += getScore(sven[i],friends[j][i]);//这里遍历的是第j个朋友的第i个手势
}//因为这里最开始 vector<string> friends(n); 最外层就是string类型的朋友的字符串,代表的出拳顺序。
}
int maxScore =0;
string Hands("SPR");
//计算最大得分
for(int i =0;i<r;i++){
//计算每个手势的最大得分
int maxRoundScore =0;
for(int j =0;j<3;j++){
int roundScore =0; //3种手势中的每轮手势的得分情况
for(int k = 0;k<n;k++){//遍历每个朋友的第i个手势
roundScore += getScore(Hands[j],friends[k][i]);
}
maxRoundScore = max(roundScore,maxRoundScore); //找到3轮中的最大一轮的分数存储起来
}
maxScore += maxRoundScore;//将3轮中每次最大的分数累加在一起
}
cout<<actualScore<<endl;
cout<<maxScore;
}
P7184 [CRCI2008-2009] MAJSTOR
详细解释:为什么是 friends[j][i]
而不是 friends[i][j]
问题背景
你正在计算 Sven 和他的朋友每轮比赛的得分。核心在于:
-
Sven 的手势 存储在字符串
sven
中,每个字符代表一轮的手势。 -
每个朋友的手势 存储在
vector<string> friends
中,每个字符串表示一个朋友在所有轮次中的手势序列。
输入的结构是:
-
sven
:一个字符串,表示 Sven 在每一轮的手势。-
例如:
sven = "SPR"
。
-
-
friends
:一个vector<string>
,每个字符串是一个朋友在每一轮的手势。-
例如:
friends = {"RPS", "PSR"}
,表示第 1 个朋友出手RPS
,第 2 个朋友出手PSR
。
-
数据组织方式
-
sven[i]
:-
表示 Sven 在第
i
轮出的手势。 -
例如,
sven[0] = 'S'
表示第一轮出剪刀。
-
-
friends[j][i]
:-
表示 第
j
个朋友 在 第i
轮 出的手势。 -
例如,
friends[0][0] = 'R'
表示第 1 个朋友在第 1 轮出的手势是R
。
-
错误的 friends[i][j]
假如写成 friends[i][j]
,它的含义是:
-
在二维数组中,
i
表示第i
个朋友(逻辑错误)。 -
j
表示这个朋友的第j
个手势。
但是,friends
的数据组织方式是 每个字符串表示一个朋友的手势序列。friends[i]
是第 i
个朋友的全部手势字符串,而手势的轮次由第二个索引决定。因此,friends[i][j]
不符合问题的含义。
正确的 friends[j][i]
写成 friends[j][i]
,它的含义是:
-
j
:第j
个朋友。 -
i
:第i
轮比赛。
通过 friends[j][i]
,你可以正确地访问:
-
第
j
个朋友 在 第i
轮 出的手势。
例如:
- 输入:
friends = {"RPS", "PSR"};
- 访问:
friends[0][0] = 'R'; // 第 1 个朋友在第 1 轮出的手势是 'R' friends[1][2] = 'R'; // 第 2 个朋友在第 3 轮出的手势是 'R'
为什么不能调换索引?
存储方式决定访问顺序
在 vector<string>
中:
-
外层索引
j
遍历朋友(每个朋友是一个字符串)。 -
内层索引
i
遍历每个朋友的手势(每个字符代表一轮比赛)。
如果你调换索引,写成 friends[i][j]
:
-
i
表示的是朋友索引,j
表示轮次,这与输入数据的存储方式相冲突。
逻辑上的错误
-
如果用
friends[i][j]
:-
i
被认为是轮次,但实际上它应该是朋友索引。 -
j
被认为是朋友索引,但实际上它应该是轮次。 -
数据访问的含义被颠倒,导致逻辑错误。
-
-
如果用
friends[j][i]
:-
j
表示朋友,i
表示轮次,符合数据存储方式。
-
举例:输入与访问
假设输入如下:
r = 3
sven = "SPR"
friends = {"RPS", "PSR"}
数据解释:
-
sven = "SPR"
:-
Sven 第 1 轮出
S
,第 2 轮出P
,第 3 轮出R
。
-
-
friends = {"RPS", "PSR"}
:-
第 1 个朋友的手势是
RPS
:-
第 1 轮出
R
,第 2 轮出P
,第 3 轮出S
。
-
-
第 2 个朋友的手势是
PSR
:-
第 1 轮出
P
,第 2 轮出S
,第 3 轮出R
。
-
-
访问数据:
- Sven 的第 1 轮手势:
sven[0] = 'S';
- 第 1 个朋友的第 1 轮手势:
friends[0][0] = 'R';
- 第 2 个朋友的第 3 轮手势:
friends[1][2] = 'R';
如果写成 friends[i][j]
,逻辑上就会出现混乱。
修复后的代码片段
实际得分:
for (int i = 0; i < r; i++) { // 遍历每轮比赛
for (int j = 0; j < n; j++) { // 遍历每个朋友
actualScore += getScore(sven[i], friends[j][i]); // 正确访问
}
}
总结
-
正确逻辑:
-
外层循环
i
遍历轮次。 -
内层循环
j
遍历每个朋友。 -
通过
friends[j][i]
访问第j
个朋友在第i
轮出的手势。
-
-
错误逻辑:
-
调换索引为
friends[i][j]
会破坏数据的访问顺序,因为friends
的结构是 朋友优先,轮次在内层。
-
数据组织方式决定了索引的顺序,friends[j][i]
是符合存储逻辑的正确写法!
原文地址:https://blog.csdn.net/qq_46243318/article/details/144037707
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!