[C++]模拟

1 篇文章 0 订阅

数组模拟操作

什么是模拟
    模拟顾名思义,就是按照题目的要求,一步步写出代码。
    题目要求怎么做就怎么做,用代码的形式描述出来。

模拟的过程
(1)读题。读懂题目的意思。
(2)建模。将问题抽象成模型,选择合理的算法和数据结构(比如定义数组来记录一组事物的状态)。
(3)代码实现。


矩阵的折叠

引言
    一张纸我们可以从中间把它对折。
    想象一下,如果给你若干个数组成的数组,我们可以把它对折起来吗?
问题
有这样一个数组int a[6]={3,5,2,6,9,1};
现在要求你,将这个数组的右半边折向左半边,重叠的数字加起来,这个数组会变成什么样子?

应该会变成4,14,8(数组的长度减半,对应元素相加)。

思考
1)如果是n个元素组成的数组,折叠后数组的长度是?
不能直接写n/2,如果n是奇数,比如5个数,折叠后应该剩3个。
折叠后数组的长度是 (n+1)/2。

2)折叠时第i个元素和第几个元素叠加?
第1个元素和第n个元素叠加,第2个元素和第n-1个元素叠加,…… ,第i个元素和第n+1-i个元素叠加


竞赛模拟真题

引言
模拟在编程比赛中出现的概率是非常高的,而且模拟题不像其他类型的题用固定的解法来做,模拟题需要根据不同的题建立不同的模型,思考出合适的解法。
想要训练解模拟题,最好的方法就是多看多做,见得多了,自己也能总结出一套合适自己的方法。这节课我们就来看几道编程比赛中的模拟真题。
龙虎斗
题目描述轩轩和凯凯正在玩一款叫《龙虎斗》的游戏,游戏的棋盘是一条线段,线段上有 n个兵营(自左至右编号1~n),相邻编号的兵营之间相隔 1厘米,即棋盘为长度为 n-1厘米的线段。i号兵营里有 ci位工兵。
轩轩在左侧,代表“龙”;凯凯在右侧,代表“虎”。 他们以 m号兵营作为分界, 靠左的工兵属于龙势力,靠右的工兵属于虎势力,而第 m 号兵营中的工兵很纠结,他们不属于任何一方。
一个兵营的气势为:该兵营中的工兵数× 该兵营到 m 号兵营的距离;参与游戏一方的势力定义为:属于这一方所有兵营的气势之和。
游戏过程中,某一刻天降神兵,共有 s1位工兵突然出现在了 p1号兵营。作为轩轩和凯凯的朋友,你知道如果龙虎双方气势差距太悬殊,轩轩和凯凯就不愿意继续玩下去了。为了让游戏继续,你需要选择一个兵营 p2,并将你手里的 s2​ 位工兵全部派往 兵营 p2​,使得双方气势差距尽可能小。
注意:你手中的工兵落在哪个兵营,就和该兵营中其他工兵有相同的势力归属(如果落在 m号兵营,则不属于任何势力)。

分析: 本题题目描述很复杂,不过读懂题目之后解题思路应该能比较清楚。
分别算出龙、虎阵营的势力(加上天降神兵的势力),如果算出来龙方势力较弱,就往龙方的兵营(或者也可能是往中立兵营)加人;如果算出来虎方势力较弱,就往虎方的兵营(或者也可能是往中立兵营)加人,要使得势力差尽量小。

#include<iostream>
#include<cmath>
using namespace std;
long long n,m,p1,p2,s1,s2,x,y,diff,c[100005]; 
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++){ //每个兵营的人数
        cin>>c[i];
    }
    cin>>m>>p1>>s1>>s2;
    for(int i=1;i<m;i++){  //龙方气势
        x+=(m-i)*c[i];
    }
    for(int i=m+1;i<=n;i++){  //虎方气势
        y+=(i-m)*c[i];
    }
    if(p1<m) x+=(m-p1)*s1;  //天降神兵加入龙方
    if(p1>m) y+=(p1-m)*s1;  //天降神兵加入虎方
    diff=abs(x-y);  //两方势力差
    p2=m;
    if(x<y){  //如果龙方弱
        for(int i=1;i<m;i++){   //寻找龙方兵营(或中立兵营)加入,使得势力差尽量小
            if(abs(x+(m-i)*s2-y)<diff){
                diff=abs(x+(m-i)*s2-y);
                p2=i;
            }
        }
    }
    else if(x>y){  //寻找虎方兵营(或中立兵营)加入,使得势力差尽量小
        for(int i=m+1;i<=n;i++){
            if(abs(y+(i-m)*s2-x)<diff){
                diff=abs(y+(i-m)*s2-x);
                p2=i;
            }
        }
    }
    cout<<p2;
    return 0;
}

简单模型+复杂模拟

报数游戏1
题目描述:有n个人围成一圈,按顺序从1到n编号。从第一个人开始报数,报数4的人退出圈子,下一个人从1开始重新报数,报数4的人退出圈子… …如此循环,直到留下最后一个人。问最后留下来的人的编号。
分析: 首先选择合适的数据类型(数组),可以利用数组来标记n个人的状态(是否离开圈子)。
一开始,n个人都在圈里,可以给数组元素全赋值为1表示在圈子里。
后面模拟报数的过程,我们一遍一遍地遍历数组,每次计数4个人在圈子里(找到了4个值为1的数组元素),则第4个人出圈(对应元素值置为0),同时要定义一个计数器记录圈子中剩的人数,当圈子里只剩1人时即停止。

#include<iostream>
using namespace std;
int a[55],n;  //定义a数组标记每个人的状态 
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){    //数组元素初值全赋为1,表示都在 
        a[i]=1;
    }
    int s=n,sum=0;   //s记录圈子里的人数 
    while(s>1){
        for(int i=1;i<=n;i++){
            sum+=a[i];        //在圈子里的人(a[i]值为1)报数 
            if(sum==4){
            a[i]=0;    //标记离开 
            sum=0;
            s--;
            }
        }
    }
    for(int i=1;i<=n;i++){  //找留下的人 
        if(a[i]){
            cout<<i;
            break;
        }
    } 
    return 0;
}
  • 22
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值