zoukankan      html  css  js  c++  java
  • Test in 01.22 T4:pogo

      这是道很有意思的模拟题。

      首先,sro XF orz

      题面:

      

      首先想到的是暴力的算法,枚举每一步操作中最顶端的数字,然后在加上顶端数字,但具体的暴力做法是需要一定的思路的,因为骰子中每一面所对的面都是固定的,所以只需要确定上,前,右三个面就可以确定所有面上的数字,然后一一枚举即可:关键代码如下:

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 int r,c,Opposite[7]={0,6,5,4,3,2,1},Top=1,Right=3,Front=2,temp;
     5 long long ans=0;
     6 int main()
     7 {
     8     //读入数据
     9     for (int i=1;i<=r;i++)
    10     {
    11         ans+=Top;
    12     if (i%2==1)//如果为奇数行做向右移动的操作,否则做向左移动的操作
    13     for (int j=1;j<c;j++)//注意操作次数为c-1
    14     {
    15         temp=Opposite[Right];
    16         Right=Top;
    17         Top=temp;//左右移动的操作中前面的点数不变
    18         ans+=Top;
    19     }
    20     else
    21         for (int j=1;j<c;j++)
    22         {
    23              temp=Opposite[Top];
    24                  Top=Right;
    25          Right=temp;
    26          ans+=Top;
    27         }
    28         temp=Opposite[Front];
    29         Front=Top;
    30         Top=temp;//向下移动的操作中右面的点数不变
    31     }
    32     cout<<ans<<endl;
    33     return 0;
    34 } 
    35                

      但是题目上的数据范围为100000,而暴力算法的时间复杂度为O(n^2),所以暴力算法只能过50%的数据。

      这时候需要提取题面中的重要信息:每面上的点数加上其所对的点数之和为7。而在每行上,每4次操作都是重复的,所以在这么多操作中存在了许多次重复的固定操作,而这些固定操作的数字和均为14,次数均为4,所以需要在读入数据直接进行特殊处理,将c转化为小于4的正整数,这样的话就不会超时了。

      但需要注意的是,如果c在处理之后值为0,在让c取膜并进行计算的同时也将r上的操作进行了,所以这时候需要对是否进行循环进行判断。下面给出AC代码:

     

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int r,c,Opposite[7]={0,6,5,4,3,2,1},Top=1,Right=3,Front=2,temp;
    long long ans=0;
    int main()
    {
        freopen("pogo.in","r",stdin);
        freopen("pogo.out","w",stdout);
        scanf("%d%d",&r,&c);
        ans=14*((c/4)*r);//直接进行重复的操作
        c=c%4;//对c进行处理
        if (c!=0)//特判
            for (int i=1;i<=r;i++)
            {
                ans+=Top;
                if (i%2==1)
                    for (int j=1;j<c;j++)
                    {
                        temp=Opposite[Right];
                        Right=Top;
                        Top=temp;
                        ans+=Top;
                    }
                else
                    for (int j=1;j<c;j++)
                    {
                        temp=Opposite[Top];
                        Top=Right;
                        Right=temp;
                        ans+=Top;
                    }
                temp=Opposite[Front];
                Front=Top;
                Top=temp;
            }
        cout<<ans<<endl;
        return 0;
    }

      前后代码差别不大。

      理解之后这道题还是很水的,但是理解起来较有难度。

      (cout如果要换成printf的话记住要用longlong类型的,第一次提交的时候用的%d结果超数据范围了T.T)

  • 相关阅读:
    提示框第三方库之MBProgressHUD
    三种ViewController跳转的异同
    性能测试学习第一天_性能测试常见术语
    JSONArray与list互转
    web service CXF工作中使用总结
    局部变量、类变量、实例变量有什么区别
    hibernate 的几种查询——工作中使用到的
    tomcat 常见启动问题小记
    文本编辑器KindEditor的使用
    kaptcha Java验证码
  • 原文地址:https://www.cnblogs.com/hinanawitenshi/p/6343580.html
Copyright © 2011-2022 走看看