zoukankan      html  css  js  c++  java
  • Ducci Sequence 解题心得

    原题贴上

    A Ducci sequence is a sequence of n-tuples of integers. Given an n-tuple of integers (a1a2, ... an), the next n-tuple in the sequence is formed by taking the absolute differences of neighboring integers:

     

     

    a1a2... an$displaystyle 
ightarrow$ (| a1 - a2|,| a2 - a3|, ... ,| an - a1|)

     

    Ducci sequences either reach a tuple of zeros or fall into a periodic loop. For example, the 4-tuple sequence starting with 8,11,2,7 takes 5 steps to reach the zeros tuple:

     

     

    (8, 11, 2, 7) $displaystyle 
ightarrow$ (3, 9, 5, 1) $displaystyle 
ightarrow$ (6, 4, 4, 2) $displaystyle 
ightarrow$ (2, 0, 2, 4) $displaystyle 
ightarrow$ (2, 2, 2, 2) $displaystyle 
ightarrow$ (0, 0, 0, 0).

     

    The 5-tuple sequence starting with 4,2,0,2,0 enters a loop after 2 steps:

     

     

    (4, 2, 0, 2, 0) $displaystyle 
ightarrow$ (2, 2, 2, 2, 4) $displaystyle 
ightarrow$ ( 0, 0, 0, 2, 2$displaystyle 
ightarrow$ (0, 0, 2, 0, 2) $displaystyle 
ightarrow$ (0, 2, 2, 2, 2) $displaystyle 
ightarrow$ (2, 0, 0, 0, 2) $displaystyle 
ightarrow$

     

     

    (2, 0, 0, 2, 0) $displaystyle 
ightarrow$ (2, 0, 2, 2, 2) $displaystyle 
ightarrow$ (2, 2, 0, 0, 0) $displaystyle 
ightarrow$ (0, 2, 0, 0, 2) $displaystyle 
ightarrow$ (2, 2, 0, 2, 2) $displaystyle 
ightarrow$ (0, 2, 2, 0, 0) $displaystyle 
ightarrow$

     

     

    (2, 0, 2, 0, 0) $displaystyle 
ightarrow$ (2, 2, 2, 0, 2) $displaystyle 
ightarrow$ (0, 0, 2, 2, 0) $displaystyle 
ightarrow$ (0, 2, 0, 2, 0) $displaystyle 
ightarrow$ (2, 2, 2, 2, 0) $displaystyle 
ightarrow$ ( 0, 0, 0, 2, 2$displaystyle 
ightarrow$ ...

     

    Given an n-tuple of integers, write a program to decide if the sequence is reaching to a zeros tuple or a periodic loop.

     

    Input 

    Your program is to read the input from standard input. The input consists of T test cases. The number of test casesT is given in the first line of the input. Each test case starts with a line containing an integer n(3$ le$n$ le$15), which represents the size of a tuple in the Ducci sequences. In the following line, n integers are given which represents the n-tuple of integers. The range of integers are from 0 to 1,000. You may assume that the maximum number of steps of a Ducci sequence reaching zeros tuple or making a loop does not exceed 1,000.

     

    Output 

    Your program is to write to standard output. Print exactly one line for each test case. Print `LOOP' if the Ducci sequence falls into a periodic loop, print `ZERO' if the Ducci sequence reaches to a zeros tuple.

    The following shows sample input and output for four test cases.

     

    Sample Input 

     

    4 
    4 
    8 11 2 7 
    5 
    4 2 0 2 0 
    7 
    0 0 0 0 0 0 0 
    6 
    1 2 3 1 2 3
    

     

    Sample Output 

     

    ZERO 
    LOOP 
    ZERO 
    LOOP


    分析:
      题目让我们求循环出现的时候和全0出现的时候, 其实,全0出现后紧接着就会出现循环,所以我们只需专注于找到循环出现。
    这里的循环也就是数字的排列出现重复,也就是发现重复即找到。
    想到去重,第一个想到的便是STL中的set可以直接保证每个键是唯一的,然而这里这并不能将重复出现的时候标记出来,达不到解题。接着就很自然的想到“标记法”,即——将每种情形和一个bool值对应,出现过记为true,没出现过记为false。每次新出现一个情形先判断对应的bool值,然后就可以判断重复没有啦。
    一种情形与一个值对应,最近正在学STL,然后立马就想到了map。
    map<A,B> 应题目要求,A为一个有序对比较适合,所以可以用一个结构体将多个数字组成一个整体,B就很自然的使用bool类型。
    可是还有一个问题,map<A,B> 里面的A必须要是定义了<操作符的,因为map判断A的唯一性必须要通过<符号比较,具体的判别机制是(a<b,b<a 有且仅有一个成立 ->a b不相等 //否则a b相等),这就需要我们重载A里的<操作符。
    按照判别机制,我如下重载
    1     bool operator <(const gro &b) const {
    2         for (int i = 0; i < n; i++){
    3             if (g[i] != b.g[i]) return g[i]<b.g[i];
    4         }
    5         return false;
    6     }

    有了这个认识,然后就可以写代码了,如下:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<map>
     4 #include<stdio.h>
     5 using namespace std;
     6 const int N = 16;
     7 bool isloop = 0;
     8 
     9 
    10 struct gro
    11 {
    12     int g[N];
    13     int n;
    14     void read ()
    15     {
    16         for (int i = 0; i < n; i++)
    17         {
    18             cin >> g[i];
    19         }
    20     }
    21     bool iszero(){
    22         for (int i = 0; i < n; i++){
    23             if (g[i] != 0){
    24                 return false;
    25             }
    26         }
    27         return true;
    28     }
    29 
    30     bool operator <(const gro &b) const {
    31         for (int i = 0; i < n; i++){
    32             if (g[i] != b.g[i]) return g[i]<b.g[i];
    33         }
    34         return false;
    35     }
    36 
    37     void change()
    38     {
    39         int temp = g[0];
    40         for (int i = 0; i < n - 1; i++)
    41         {
    42             g[i] = abs(g[i] - g[i + 1]);
    43         }
    44         g[n - 1] = abs(temp - g[n - 1]);
    45     }
    46 
    47 } g1;
    48 
    49 
    50 
    51 
    52 
    53 map <gro, bool> group;
    54 
    55 int main()
    56 {
    57     int T;
    58     cin >> T;
    59     while (T--){
    60         cin >> g1.n;
    61         g1.read();
    62         group.clear();    // 因为有多组数据,记得要清空!!!
    63 group[g1] = true; 64 for (int k = 0; k < 1000; k++){ 65 g1.change(); 66 if (group[g1] == true){ 67 isloop = true; 68 break; 69 } 70 group[g1] = true; //一定要记得!!! 71 } 72 if (g1.iszero() == true){ 73 puts("ZERO"); 74 } 75 else { 76 puts("LOOP"); 77 } 78 bool isloop = false; 79 } 80 81 return 0; 82 }

    骚年,加油奋斗吧,毕竟水题。



  • 相关阅读:
    Ubuntu 16 安装redis客户端
    crontab 参数详解
    PHP模拟登录发送闪存
    Nginx配置端口访问的网站
    Linux 增加对外开放的端口
    Linux 实用指令之查看端口开启情况
    无敌的极路由
    不同的域名可以指向同一个项目
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error
    Redis 创建多个端口
  • 原文地址:https://www.cnblogs.com/shawn-ji/p/4647610.html
Copyright © 2011-2022 走看看