杭电ACM1979题的一种解法

HDU ACM 1979的一种解法

1.        题目

题目原文见http://acm.hdu.edu.cn/showproblem.php?pid=1979

2.        数据

2.1.       可逆素数表

int prime_digits_buff[MAX_BUFF][4];

用数组存放可逆素数的4位数。

2.2.       可逆素数标识

int is_reverse_prime[10000]

例如,1192不是可逆素数,因此is_reverse_prime[1192]01193是可逆素数,因此is_reverse_prime[1193]1

2.3.       可逆素数索引

typedef struct

{

  int count;

  int list[MAX_BUFF];

} prime_link_t;

prime_link_t prime_link_buff[10];

 

按可逆素数的最高位来组织可逆素数的索引表。例如,1193将存放在prime_link_buff[1]中,3911将存放在prime_link_buff[3]中。

2.4.       解矩阵

typedef struct

{

  int val[4]; /*矩阵的4个可逆素数*/

  int digits[4][4]; /*矩阵的每一位数值*/

} solution_t;

char solution_buff[MAX_SOLUTION][17]; /*矩阵字符串*/

3.        算法

3.1.       主算法

求出10009999之间的可逆素数及其总数reverse_prime_count

建立is_reverse_prime

建立prime_link_buff

for (i = 0; i < prime_count; i ++)

{

    prime_digits_buff[i]取出一个可逆素数;

    if(该可逆素数的4位数在prime_link_buff中的count都大于0

{

        根据这4位数通过组合循环从prime_link_buff中找出可逆素数来构造解矩阵,并在构造后把符合条件的矩阵存入solution_buff

}

}

solution_buff排序;

输出solution_buff

3.2.       构造解矩阵算法

以一个可逆素数的4位数为第1位数,通过递归来寻找4可逆素数。例如,对于9133,可找到第1位分别是91334个数9173155938213391

void compose_solution (int first_digit[4], int i, solution_t *solution)

{

  int j, k;

  if (i < 4)

  {

    prime_link_t *link = &prime_link_buff[first_digit[i]];

    for (k = 0; k < link->count; k++)

    {

      int tk = link->list[k];

      for (j = 0; j < i && solution->val[j] != tk; j++);

      if (j == i)

      {

        int modula = 1;

        solution->val[i] = tk;

        for (j = 0; j < 4; j++)

        {

          int remain = tk%10;

          solution->digits[i][3-j] = remain;

          tk /= 10;

        }

        if (check_solution(i, solution))

        {

          compose_solution(first_digit, i+1, solution);

        }

      }

    }

  }

3.3.       判断解矩阵算法

int check_solution(int i, solution_t *solution)

{

  int status;

  if (i == 0) /*如果矩阵中只有第1*/

  {

    /*只要该数的某1位不可能是可逆素数的第1位就返回0*/

    status = (prime_link_buff[solution->digits[i][1]].count == 0 ||

        prime_link_buff[solution->digits[i][2]].count == 0 ||

        prime_link_buff[solution->digits[i][3]].count == 0) ? 0 : 1;

  }

  else if (i == 3) /*如果矩阵中已有4*/

  {

    int j;

    int new_number;

    for (j = 1; j < 4; j++)

    {

      int new_number = compose_row_number(j, solution);/*行构成的数*/

      if (is_reverse_prime[new_number] == 0)

      {

        status = 0;

        break;

      }

    }

    if (status)

    {

      new_number = compose_diagonal_number_1(solution); /*对角线1构成的数*/

      if (is_reverse_prime[new_number] == 0)

      {

        status = 0;

      }

      else

      {

        new_number = compose_diagonal_number_2(solution); /*对角线2构成的数*/

        if (is_reverse_prime[new_number] == 0)

        {

          status = 0;

        }

        else

        {

          /*存放解*/

          int k;

          for (k = j = 0; k < 4; k++, j += 4)

          {

            itoa(solution->val[k], &solution_buff[solution_count][j], 10);

          }

          solution_count++;

        }

      }

    }

  }

  return status;

}

4.        结果

由于该题的输出结果是唯一的,因此递交评判的程序不必包含计算过程,只要按格式要求输出结果就能AC

#include<stdio.h>

char *solution[] =

{

  "1193100992213191",

  "1193102190293911",

  "1193120192093911",

  "1193122990013191",

  "1193704336973911",

  "1193725338213319",

  "1193725338513319",

  "1193745738213719",

  "1193796334073911",

  "1193900112293191",

  "1193901116693911",

  "1193901316693911",

  "1193902910213911",

  "1193904113993371",

  "1193920912013911",

  "1193922110093191",

  "1193925738213319",

  "1193925738513319",

  "1193947913813917",

  "1193966111093911",

  "1193966131093911",

  "1193992310093191",

  "1733106994913371",

  "1733128395213319",

  "1733128395513319",

  "1733148795213719",

  "1733194996013371",

  "1733922710213719",

  "1733993114093911",

  "1913100992213911",

  "1913102190293191",

  "1913103394973191",

  "1913106991613191",

  "1913106991613391",

  "1913120192093191",

  "1913122990013911",

  "1913143997813917",

  "1913161996013191",

  "1913190192093391",

  "1913720732213719",

  "1913794933013191",

  "1913900112293911",

  "1913900132993911",

  "1913902910213191",

  "1913917333893391",

  "1913920912013191",

  "1913922110093911",

  "1933128395213719",

  "1933128395513719",

  "1933161996013191",

  "1933902910913191",

  "1933913317893391",

  "1933983337193191",

  "1933987133193391",

  "3191100992211193",

  "3191100999231193",

  "3191102190291913",

  "3191109190291933",

  "3191120192091913",

  "3191122990011193",

  "3191330179491913",

  "3191371998331933",

  "3191702712239173",

  "3191900112291193",

  "3191902910211913",

  "3191916110691913",

  "3191920912011913",

  "3191922110091193",

  "3191934118797193",

  "3191949710331913",

  "3191960116191913",

  "3191960116191933",

  "3319382172531193",

  "3319382192571193",

  "3319385172531193",

  "3319385192571193",

  "3319952112831733",

  "3319955112831733",

  "3371139990411193",

  "3371382112599133",

  "3371382115599133",

  "3371722912019173",

  "3371784112599173",

  "3371949110691733",

  "3371960119491733",

  "3391178991331933",

  "3391331998711933",

  "3391338991731913",

  "3391382112599173",

  "3391382115599173",

  "3391916110691913",

  "3391920919011913",

  "3719102192271733",

  "3719322172071913",

  "3719382174571193",

  "3719952112831933",

  "3719952114871733",

  "3719955112831933",

  "3911100992211913",

  "3911102190291193",

  "3911110996611193",

  "3911120192091193",

  "3911122990011913",

  "3911140999311733",

  "3911166990111193",

  "3911166990131193",

  "3911310996611193",

  "3911329990011913",

  "3911340779631193",

  "3911352712839133",

  "3911352715839133",

  "3911369770431193",

  "3911752912839133",

  "3911752915839133",

  "3911754712839173",

  "3911900112291913",

  "3911902910211193",

  "3911920912011193",

  "3911922110091913",

  "3911974918317193",

  "3917138194791193",

  "3917978114391913",

  "7193183197493911",

  "7193187993413191",

  "9133125938213371",

  "9133128335273911",

  "9133128375293911",

  "9133155938213371",

  "9133158335273911",

  "9133158375293911",

  "9173120172293371",

  "9173122370273191",

  "9173125938213391",

  "9173125978413371",

  "9173128375473911",

  "9173155938213391"

};

 

int main()

{

  int i, k;

  int count = sizeof(solution) / sizeof(char *);

  for (i = 0; i < count; i++)

  {

    for (k = 0; k < 16; k++)

    {

      printf("%c", solution[i][k]);

      if (k > 0 && k % 4 == 3) printf("/n");

    }

    if (i < count-1) printf("/n");

  }

  return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值