自学内容网 自学内容网

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 中,每个字符串表示一个朋友在所有轮次中的手势序列。

输入的结构是:

  1. sven:一个字符串,表示 Sven 在每一轮的手势。

    • 例如:sven = "SPR"

  2. friends:一个 vector<string>,每个字符串是一个朋友在每一轮的手势。

    • 例如:friends = {"RPS", "PSR"},表示第 1 个朋友出手 RPS,第 2 个朋友出手 PSR


数据组织方式

  1. sven[i]

    • 表示 Sven 在第 i 轮出的手势。

    • 例如,sven[0] = 'S' 表示第一轮出剪刀。

  2. 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 表示轮次,这与输入数据的存储方式相冲突。

逻辑上的错误

  1. 如果用 friends[i][j]

    • i 被认为是轮次,但实际上它应该是朋友索引。

    • j 被认为是朋友索引,但实际上它应该是轮次。

    • 数据访问的含义被颠倒,导致逻辑错误。

  2. 如果用 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)!