C++ Introductory Algorithm Training - Jiugong rearrangement, lucky number (with code)

Example - Jiugong rearrangement

topic background

        For example, in the Jiugong grid in the first picture below, there are number cards from 1 to 8, and there is another grid that is empty. Cards in grids adjacent to empty spaces can be moved into empty spaces. After several moves, the situation shown in the second figure can be formed.

        We record the situation of the first picture as: 12345678.

        Record the situation of the second picture as: 123.46758

        Apparently numbers are recorded from top to bottom, left to right, and spaces are recorded as periods.

        The task of this topic is to know the initial state and final state of the Jiugong, and find out how many steps can be reached at least. If it cannot be reached no matter how many steps, output -1.

input format

        The first line of input contains the initial state of the Jiugong, and the second line contains the final state of the Jiugong.

output format

        Output the least number of steps, or -1 if no solution exists.

Input and output samples

enter

12345678.
123.46758

output

3

Reference Code

#include<iostream>
#include<queue>
#include<map>
using namespace std;
int dx[4]={1,-1,3,-3};
map<string,int> mp;
string s,e;
struct node
{
    string str;
    int step;
};
bool no(int x,int y)
{
    if(x==2&&y==3) return 1;
    if(x==3&&y==2) return 1;
    if(x==5&&y==6) return 1;
    if(x==6&&y==5) return 1;
    return 0;
}
void bfs()
{
    queue<node> q;
    node tmp,now;
    tmp.step=0;
    tmp.str=s;
    q.push(tmp);
    while(q.size())
    {
        now=q.front();q.pop();
        if(now.str==e)
        {
            cout<<now.step<<endl;
            return;
        }
        int x=now.str.find('.');
        for(int i=0;i<4;i++)
        {
            s=now.str;
            int y=x+dx[i];
            if(y<0||y>8) continue;
            if(no(x,y)) continue;
            swap(s[x],s[y]);
            if(mp[s]) continue;
            mp[s]=1;
            tmp.step=now.step+1;
            tmp.str=s;
            q.push(tmp);
        }
    }
    cout<<"-1"<<endl;
}
int main()
{
    cin>>s>>e;
    mp[s]=1;
    bfs();
    return 0;
}

Inference from one example to another - lucky number

topic background

        Lucky numbers are named after Ulam, a Polish mathematician. It is generated using a "sieve method" similar to generating prime numbers.

First write the natural numbers 1,2,3,4,5,6,....         from 1

        1 is the first lucky number.

        We start with the number 2. Delete all items whose serial numbers can be divisible by 2, and change to: 1 _ 3 _ 5 _ 7 _ 9  …

        Squeeze them down and reorder them as: 1 3 5 7 9 ... .

        At this time, 3 is the second lucky number, and then delete all the numbers in the serial number positions that are divisible by 3. Note that it is the position of the serial number, not whether the number itself can be divisible by 3!! The deleted ones should be 5, 11, 17, ...

        At this time, 7 is the third lucky number, and then delete the sequence number position that can be divisible by 7 (19,39,...)

        The final remaining sequence is something like: 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, ...

input format

        Enter two positive integers mn, separated by spaces (m < n < 1000*1000)

output format

        The program outputs the number of lucky numbers between m and n (excluding m and n).

Input and output samples

input sample

1 20

output sample

5

Reference Code

# include<stdio.h>
# define MAX 50000

int create_luck(int * );
int num_luck(int *,int,int,int);

int main(void)
{
  int luck[MAX] = {0};
  int max,n,i;
  int num1,num2;/*标定范围*/

  max = create_luck(luck);/*幸运数生成*/
  scanf("%d%d",&num1,&num2);
  n = num_luck(luck,max,num1,num2);/*计算num1到num2之间的幸运数个数*/
  printf("%d\n",n);
  /*for(i=0;i<max;i++){
    printf("%d\t",luck[i]);//遍历幸运数
  }*/
  return 0;
}

int create_luck(int * luck)
{
  /*1~2*MAX的幸运数*/
  int i,j;
  int point_pre=1;/*point_pre用来标记被除数数组下标,也就是上一次循环找到的幸运数*/
  int point_max=MAX;/*point_max用来标记遍历一遍完成删除之后剩余的元素个数*/

  /*原始奇数数组,第一次将偶数完全删除,所以所有幸运数在奇数中生成即可*/
  for(i=0;i<MAX;i++){
    luck[i] = 2*i+1;
  }
  /*生成幸运数*/
  while(point_pre < point_max){
    for(j = point_pre, i = point_pre; j<point_max; j++){/*i,j从point_pre开始,因为point_pre之前的数都已经是幸运数了*/
      if((j+1) % luck[point_pre] != 0){
        luck[i] = luck[j];
        i++;
      }
    }
    point_pre++;/*幸运数个数加1,也是内层循环初始值后移1*/
    point_max = i;/*便遍历一遍之后,i之前的符合局部条件(取余不为0),point_max则划分界限*/
  }
  /*注意:循环完成时,point_pre之前的数都是幸运数,
  但是数组定义长为MAX,point_max之后的数(MAX-point_pre个)是无用的
  */

  return point_max;
}
int num_luck(int * luck,int max,int num1,int num2)
{
  int i,n=0;

  for(i=0;i < max;i++){/*i<point_max是为了确保不会找到无用的数组后半部分*/
    if(luck[i] >= num2)
      break;
    else if(luck[i] > num1)/*不包含num1和num2*/
      n++;
  }

  return n;
}

Guess you like

Origin blog.csdn.net/leyang0910/article/details/131028726