Postal Vans

来源:互联网 发布:做平面图用什么软件 编辑:程序博客网 时间:2024/04/30 04:47

题意:摘自NOCOW翻译(http://www.nocow.cn/index.php/Translate:USACO/vans)

描述

郊区呈矩形,有四条东西方向的街道和N(1<=N<=1000)条南北方向的街道。在郊区的西北角有一个邮局。

如N=5时,郊区如下图所示,圆点表示邮局,直线表示街道。

postal1.gif

每天邮政卡车从邮局出发,每个十字路口(包括边界和四角)经过且只经过一次。现在邮局希望知道邮政货车行驶的路线有几种。 例如,下面两幅图表示的是满足上图的两条路线

postal2.gif

另一个例子,下面四幅图表示了当N=3时的全部四种情况

postal3.gif

[编辑]格式

PROGRAM NAME: vans

INPUT FORMAT:

(file vans.in)

INPUT FORMAT 一行:一个数值N

OUTPUT FORMAT:

(file vans.out) 一行: 到INPUT中给出的街道的路径总数

[编辑]SAMPLE INPUT

 4

[编辑]SAMPLE OUTPUT

 12

解题思路:

  1. 参考“北极天南星”的解题报告
  2. 需要高精度计算,用数组来代表一个大数。根据进位借位原理实现大数的加法和减法,乘法直接用多次加法来实现(基本都是乘2乘3,乘较大数的乘法只用过2次,所以用加法实现足以)
  3. 最后特殊的dp[2]的算法:dp[i]=dp[i+2]+dp[i+1]-dp[i+3]+sum[i+2]×2(公式转自北极天南星解题报告中),根据这个式子求出dp[2]之后,还需要额外加上sum[3]

代码

/*ID: zc.rene1LANG: CPROG: vans */#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX_N 1000#define BITS 512int N;int f[MAX_N + 1][BITS];int sum[MAX_N + 1][BITS];void Initial(FILE *fin){    fscanf(fin, "%d", &N);    memset(f, 0, sizeof(f));    memset(sum, 0, sizeof(sum));    f[N][0] = 1;    sum[N][0] = 1;}int GetRect(int i, int j){    int ret = 2 * (j - i);    if (i + 1 == j)    {ret++;    }    if (j + 1 == N)    {ret++;    }    if (i == 2)    {ret++;    }    return ret;}void Add(int *a, int *b, int *c){    //a + b = c    int remain = 0;    int k, temp;    for (k=0; k<BITS; k++)    {temp = a[k] + b[k] + remain;c[k] = temp % 10;remain = temp / 10;    }}void Minus(int *a, int *b, int *c){    //a - b = c    int remain = 0;    int k, temp;    for (k=0; k<BITS; k++)    {temp = a[k] - b[k] - remain;if (temp < 0){    temp += 10;    remain = 1;}else{    remain = 0;}c[k] = temp;    }}void Multiply(int *a, int times, int *b){    //a * times = b    int j;    int temp[BITS];    memcpy(temp, a, BITS * sizeof(int));    memset(b, 0, BITS * sizeof(int));    for (j=1; j<=times; j++)    {Add(b, temp, b);    }}void PrintSeq(int *seq, FILE *fout){    int i, flag = 0;    for (i=BITS-1; i>=0; i--)    {if (seq[i] != 0){    flag = 1;}if (flag == 1){    fprintf(fout, "%d", seq[i]);}    }    if (flag == 0)    {fprintf(fout, "0\n");    }    else    {fprintf(fout, "\n");    }}void DP(FILE *fout){    int i, j;    int temp[BITS];    //f[N - 1] && f[N - 2]    for (i=N-1; i>=N-2 && i>=2; i--)    {for (j=i+1; j<=N; j++) {    Multiply(f[j], GetRect(i, j - 1), temp);    Add(f[i], temp, f[i]);}Add(sum[i + 1], f[i], sum[i]);    }    for (i=N-3; i>=3; i--)    {Multiply(sum[i + 2], 2, temp);Minus(temp, f[i + 3], temp);Add(temp, f[i + 1], temp);Add(temp, f[i + 2], f[i]);Add(sum[i + 1], f[i], sum[i]);    }    if (N - 2 > 2)    {i = 2;Multiply(sum[i + 2], 2, temp);Minus(temp, f[i + 3], temp);Add(temp, f[i + 1], temp);Add(temp, f[i + 2], f[i]);//f[2] is special, f[2] must add sum[3] to create the right answerAdd(f[i], sum[i + 1], f[i]);    }        Multiply(f[2], 2, f[2]);    PrintSeq(f[2], fout);}int main(void){    FILE *fin, *fout;    fin = fopen("vans.in", "r");    fout = fopen("vans.out", "w");    Initial(fin);    DP(fout);    return 0;}



0 0
原创粉丝点击