鱼C论坛

 找回密码
 立即注册
查看: 1337|回复: 6

[已解决]计算鸭玩耍(C++)

[复制链接]
发表于 2019-7-26 18:24:28 | 显示全部楼层 |阅读模式
30鱼币
A. 计算鸭玩耍
描述
计算鸭正在一块无穷打的网格地面上玩耍,他站在A位置
计算鸭准备了n个指令a[i]
对于每个指令,计算鸭都会执行如下操作
1:往当前方向移动a[i]的距离
2:往右转90度,重复a[i]次

计算鸭决定执行这n个指令T次,假设执行完后停留在了B位置,请问A与B的曼哈顿距离是多少
曼哈顿距离指的是两个点的x坐标的绝对值之差与y坐标的绝对值之差的和
  输入
3 1
1 2 3
输出
2
最佳答案
2019-7-26 18:24:29
本帖最后由 Neverturnback 于 2019-7-28 03:54 编辑

/***************
程序思路:
一,单个旋转角度是90度,所以总共只有4个方向,两组相反的方向移动的距离和的差值之和就是曼哈顿距离
二,把执行n条指令看成一个整体,每一次执行完n条指令的曼哈顿距离都相等只是方向不同,有3种情况:
   1.方向不变,那么把这n条指令执行T次,所得到的曼哈顿就是用T乘以单个n的曼哈顿距离
   2.方向为原来的相反方向,那么T为单数,曼哈顿距离为单个n的曼哈顿距离,T为偶数,曼哈顿距离为0(和思路一的原理类似)
   3.方向改变90度(无论顺时针改变还是逆时针改变都一样), 用T%4(和思路一的原理类似具体看后面代码)
***************/
#include <iostream>
using namespace std;  //这边偷懒了,严格来说不能打开全部权限,只打开cin,cout,endl的权限

#define CMDMAX 100 //最大指令个数

struct MdMessage{
        int nMD;
        char changeAngle;
};

void GetNMD(int* nCmd, MdMessage* nMD, int cmdNum)  //执行完n条指令后的曼哈顿距离和与初始方向相比改变的方向角度
{
        int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;//sum0记录与初始方向偏差0度的方向移动的总距离, sum1记录与初始方向偏差90度的方向移动的总距离
                                                   //sum2记录与初始方向偏差180度的方向移动的总距离, sum3记录与初始方向偏差270度的方向移动的总距离
        int offsetDirection = 0;//当前起始方向与初始方向的偏差
        int xMD = 0, yMD = 0;

        for (int i = 0; i < cmdNum; ++i)
        {
                switch (nCmd[i] % 4 + offsetDirection)//以初始方向为参考点时,每一次旋转方向不一定和初始方向一致,所以用offsetDirection记录当前起始方向方向与初始方向的偏差
                {
                case 0:
                {
                                  offsetDirection = 0;
                                  sum0 += nCmd[i];
                }break;
                case 1:
                {
                                  offsetDirection = 1;
                                  sum1 += nCmd[i];
                }break;
                case 2:
                {
                                  offsetDirection = 2;
                                  sum2 += nCmd[i];
                }break;
                case 3:
                {
                                  offsetDirection = 3;
                                  sum3 += nCmd[i];
                }break;
                }
        }

        xMD = sum0 > sum2 ? sum0 - sum2 : sum2 - sum0; //x的绝对值之差(这里假设了初始方向为北,初始方向为哪个方向都一样,只要把xMD, 和yMD的值交换就行了)
        yMD = sum1 > sum3 ? sum1 - sum3 : sum3 - sum1; //y的绝对值之差

        nMD->nMD = xMD + yMD; //执行n条指令后的曼哈顿距离
        nMD->changeAngle = offsetDirection; //执行完n条指令后与初始方向的偏差
}

int GetTn_MD(int T, MdMessage const & nMD) //将n条指令执行T次后的曼哈顿距离
{
        switch (nMD.changeAngle)
        {
        case 0: //执行n条指令后方向不变
                return nMD.nMD * T; //这里用了return 所以每个case后面没跟break
        case 1:
        case 3:  //执行n条指令后方向改变90度
        {
                          switch (T % 4)
                          {
                          case 0:
                                  return 0;
                          case 1:
                          case 3:
                                  return nMD.nMD;
                          case 2:
                                  return nMD.nMD * 2;
                          }
        }
        case 2:  //执行n条指令后方向改变180度
                return nMD.nMD * (T % 2);
        }
}

int main()
{
        int nCmd[CMDMAX], cmdNum = 0, T = 0;
        MdMessage nMD;

        cout << "请输入指令的个数(必须为不大于100的非负整数,回车结束输入):";
        cin >> cmdNum; //这里偷个懒,要判断输入的是不大于100的非负整数才行
        cout << "请输入n个指令的次数(必须为非负整数,回车结束输入):";
        cin >> T; //偷懒同上

        cout << "请输入指令(必须为非负整数,每个指令之间用空格隔开,当行不够时换行,最后一个指令结束后回车结束输入):";
        for (int i = 0; i < cmdNum; ++i)
                cin >> nCmd[i]; //这里我也偷懒了,要判断输入的是非负整数

        GetNMD(nCmd, &nMD, cmdNum);

        cout << "将n条指令执行T次后曼哈顿距离为:"<<GetTn_MD(T, nMD)<<endl;

        getchar();//读取缓冲区的回车符
        getchar();//暂停程序好观察结果


        return 0;
}

最佳答案

查看完整内容

/*************** 程序思路: 一,单个旋转角度是90度,所以总共只有4个方向,两组相反的方向移动的距离和的差值之和就是曼哈顿距离 二,把执行n条指令看成一个整体,每一次执行完n条指令的曼哈顿距离都相等只是方向不同,有3种情况: 1.方向不变,那么把这n条指令执行T次,所得到的曼哈顿就是用T乘以单个n的曼哈顿距离 2.方向为原来的相反方向,那么T为单数,曼哈顿距离为单个n的曼哈顿距离,T为偶数,曼哈顿距离为0(和思路一的原理 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-7-26 18:24:29 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Neverturnback 于 2019-7-28 03:54 编辑

/***************
程序思路:
一,单个旋转角度是90度,所以总共只有4个方向,两组相反的方向移动的距离和的差值之和就是曼哈顿距离
二,把执行n条指令看成一个整体,每一次执行完n条指令的曼哈顿距离都相等只是方向不同,有3种情况:
   1.方向不变,那么把这n条指令执行T次,所得到的曼哈顿就是用T乘以单个n的曼哈顿距离
   2.方向为原来的相反方向,那么T为单数,曼哈顿距离为单个n的曼哈顿距离,T为偶数,曼哈顿距离为0(和思路一的原理类似)
   3.方向改变90度(无论顺时针改变还是逆时针改变都一样), 用T%4(和思路一的原理类似具体看后面代码)
***************/
#include <iostream>
using namespace std;  //这边偷懒了,严格来说不能打开全部权限,只打开cin,cout,endl的权限

#define CMDMAX 100 //最大指令个数

struct MdMessage{
        int nMD;
        char changeAngle;
};

void GetNMD(int* nCmd, MdMessage* nMD, int cmdNum)  //执行完n条指令后的曼哈顿距离和与初始方向相比改变的方向角度
{
        int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;//sum0记录与初始方向偏差0度的方向移动的总距离, sum1记录与初始方向偏差90度的方向移动的总距离
                                                   //sum2记录与初始方向偏差180度的方向移动的总距离, sum3记录与初始方向偏差270度的方向移动的总距离
        int offsetDirection = 0;//当前起始方向与初始方向的偏差
        int xMD = 0, yMD = 0;

        for (int i = 0; i < cmdNum; ++i)
        {
                switch (nCmd[i] % 4 + offsetDirection)//以初始方向为参考点时,每一次旋转方向不一定和初始方向一致,所以用offsetDirection记录当前起始方向方向与初始方向的偏差
                {
                case 0:
                {
                                  offsetDirection = 0;
                                  sum0 += nCmd[i];
                }break;
                case 1:
                {
                                  offsetDirection = 1;
                                  sum1 += nCmd[i];
                }break;
                case 2:
                {
                                  offsetDirection = 2;
                                  sum2 += nCmd[i];
                }break;
                case 3:
                {
                                  offsetDirection = 3;
                                  sum3 += nCmd[i];
                }break;
                }
        }

        xMD = sum0 > sum2 ? sum0 - sum2 : sum2 - sum0; //x的绝对值之差(这里假设了初始方向为北,初始方向为哪个方向都一样,只要把xMD, 和yMD的值交换就行了)
        yMD = sum1 > sum3 ? sum1 - sum3 : sum3 - sum1; //y的绝对值之差

        nMD->nMD = xMD + yMD; //执行n条指令后的曼哈顿距离
        nMD->changeAngle = offsetDirection; //执行完n条指令后与初始方向的偏差
}

int GetTn_MD(int T, MdMessage const & nMD) //将n条指令执行T次后的曼哈顿距离
{
        switch (nMD.changeAngle)
        {
        case 0: //执行n条指令后方向不变
                return nMD.nMD * T; //这里用了return 所以每个case后面没跟break
        case 1:
        case 3:  //执行n条指令后方向改变90度
        {
                          switch (T % 4)
                          {
                          case 0:
                                  return 0;
                          case 1:
                          case 3:
                                  return nMD.nMD;
                          case 2:
                                  return nMD.nMD * 2;
                          }
        }
        case 2:  //执行n条指令后方向改变180度
                return nMD.nMD * (T % 2);
        }
}

int main()
{
        int nCmd[CMDMAX], cmdNum = 0, T = 0;
        MdMessage nMD;

        cout << "请输入指令的个数(必须为不大于100的非负整数,回车结束输入):";
        cin >> cmdNum; //这里偷个懒,要判断输入的是不大于100的非负整数才行
        cout << "请输入n个指令的次数(必须为非负整数,回车结束输入):";
        cin >> T; //偷懒同上

        cout << "请输入指令(必须为非负整数,每个指令之间用空格隔开,当行不够时换行,最后一个指令结束后回车结束输入):";
        for (int i = 0; i < cmdNum; ++i)
                cin >> nCmd[i]; //这里我也偷懒了,要判断输入的是非负整数

        GetNMD(nCmd, &nMD, cmdNum);

        cout << "将n条指令执行T次后曼哈顿距离为:"<<GetTn_MD(T, nMD)<<endl;

        getchar();//读取缓冲区的回车符
        getchar();//暂停程序好观察结果


        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-7-26 20:46:14 | 显示全部楼层
我没有看懂题
“计算鸭准备了n个指令a[i]”
n等于几?n是一个变量?
a[i]是什么?和n有什么关系?

“1:往当前方向移动a[i]的距离
2:往右转90度,重复a[i]次”
同样,不明白a[i]指的是什么

“输入
3 1
1 2 3
输出
2”

我能明白这个输出2指的是A与B的曼哈顿距离,那些输入表示什么?
第1行的3和1表示什么?
第2行的1 2 3又表示什么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-7-26 20:46:46 | 显示全部楼层
还有,题目来自哪里?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-7-26 22:09:57 | 显示全部楼层
我也是,看了半天没看懂题,按什么意思这个输入也凑不出来2的输出
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-7-26 23:22:51 | 显示全部楼层
oooo
oxoo

(x)表示鸭子的位置
第一行输入,3表示输入3个数据,1是执行的次数
第二行输入 1,2,3
运行第一个输入时,输入为1,假设鸭子朝向是↑
oxoo
oooo
此时方向为→
运行第二个输入时,输入为2,
ooox
oooo
经过两次右转,方向朝←
运行第三个输入是,输入为3
xooo
oooo
方向朝↓,
与原始的情况相比
xooo
oyoo,
x轴y轴分别差1位,相加等于2
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-7-26 23:46:38 | 显示全部楼层
本帖最后由 zhouyj6516 于 2019-7-26 23:50 编辑
#include <iostream>
using namespace std;
int main()
{
    int direction=0;//0:x轴正方形,1:y轴负方向,2:x轴负方向,3:y轴正方向
    int n=0;
    int T=0;
    int x=0;
    int y=0;
    int a[100]={0};
    cin >> n;
    cin >> T;
    for (int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    while(T--)
    {
        for (int i=0;i<n;i++)
        {
            if (direction==0)
            {
                x+=a[i];
                direction+=a[i];
            }
            else if (direction==1)
            {
                y-=a[i];
                direction+=a[i];
            }
            else if (direction==2)
            {
                x-=a[i];
                direction+=a[i];
            }
            else if (direction==3)
            {
                y+=a[i];
                direction+=a[i];
            }
            direction%=4;
        }
    }
        if (x<0) x=-x;
        if (y<0) y=-y;
    cout << x+y << endl;
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-4 01:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表