解题报告——POJ 1579

Description

We all love recursion! Don‘t we?

Consider a three-parameter recursive function w(a, b, c):

if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 
1

if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: 
w(20, 20, 20)

if a < b and b < c, then w(a, b, c) returns: 
w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)

otherwise it returns: 
w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)

This is an easy function to implement. The problem is, if implemented directly, for moderate values of a, b and c (for example, a = 15, b = 15, c = 15), the program takes hours to run because of the massive recursion.

Input

The input for your program will be a series of integer triples, one per line, until the end-of-file flag of -1 -1 -1. Using the above technique, you are to calculate w(a, b, c) efficiently and print the result.

Output

Print the value for w(a,b,c) for each triple.

Sample Input

1 1 1
2 2 2
10 4 6
50 50 50
-1 7 18
-1 -1 -1

Sample Output

w(1, 1, 1) = 2
w(2, 2, 2) = 4
w(10, 4, 6) = 523
w(50, 50, 50) = 1048576
w(-1, 7, 18) = 1

------------------------------------------------------------------------------------------------------------------------------------------这道题与递归相关,为入门级难度。对于规模递减缓慢的递归问题来说,存在的策略有三种:1. 记忆。当情况为可数时,可以存储中间过程计算的结果,并在其他分支的迭代式遇到同样算式时直接调用结果,如本题。2. 寻找直接求解式而非迭代式,即寻找其中的数学性质,如斐波那契数列的计算。3. 尝试是否能够把问题转化为非递归式,如二分法。
#include <stdio.h>
#include <stdlib.h>

/* Function Run Fun
/  PKU OJ
/  ID:1579
/  直接采用递归是低效的,此题采用记忆法,将计算出的中间量进行记忆,从而减少重复迭代造成的效率损失
*/

int memory[21][21][21];

int W(int a, int b, int c)
{
    if(a <= 0 || b <= 0 || c <= 0)
    {
        return 1;
    }
    else if(a > 20 || b > 20 || c > 20)
    {
        memory[20][20][20] = W(20, 20, 20);
        return memory[20][20][20];
    }
    else if((int)memory[a][b][c] != 0)
    {
        return memory[a][b][c];
    }
    else if(a < b && b < c)
    {
        memory[a][b][c - 1] = W(a, b, c - 1);
        memory[a][b - 1][c - 1] = W(a, b - 1, c - 1);
        memory[a][b - 1][c] = W(a, b - 1, c);
        return memory[a][b][c - 1] + memory[a][b - 1][c - 1] - memory[a][b - 1][c];
    }
    else
    {
        memory[a-1][b][c] = W(a - 1, b, c);
        memory[a-1][b-1][c] = W(a - 1, b-1, c);
        memory[a-1][b][c-1] = W(a - 1, b, c-1);
        memory[a-1][b-1][c-1] = W(a - 1, b-1, c-1);
        return memory[a-1][b][c] + memory[a-1][b-1][c] + memory[a-1][b][c-1] - memory[a-1][b-1][c-1];
    }
}

int main()
{
    int a[100], b[100],c[100];
    int index = 0;
    while(scanf("%d%d%d", &a[index], &b[index], &c[index]) != EOF)
    {
        if(a[index] == -1 && b[index] == -1 && c[index] == -1)
        {
            break;
        }
        index++;

    }
    int i;
    for(i = 0; i < index; i++)
    {
        printf("w(%d, %d, %d) = %d\n", a[i], b[i], c[i], W(a[i], b[i], c[i]));
    }
    return 0;
}
时间: 2024-11-07 06:40:56

解题报告——POJ 1579的相关文章

解题报告——POJ 2002

Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 16908   Accepted: 6425 Description A square is a 4-sided polygon whose sides have equal length and adjacent sides form 90-degree angles. It is also a polygon such that rotating abou

解题报告——POJ 2623

Sequence Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15792   Accepted: 4409 Description Given a sequence of N nonnegative integers. Let's define the median of such sequence. If N is odd the median is the element with stands in

解题报告——POJ 2299

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 44671   Accepted: 16240 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

解题报告——POJ 2726

Holiday Hotel Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8204   Accepted: 3211 Description Mr. and Mrs. Smith are going to the seaside for their holiday. Before they start off, they need to choose a hotel. They got a list of hotels

poj 3020 Antenna Placement 解题报告

题目链接:http://poj.org/problem?id=3020 题目意思:首先,请忽略那幅有可能误导他人成分的截图(可能我悟性差,反正有一点点误导我了). 给出一幅 h * w 的图,  “ * ” 表示 point of interest,“ o ” 忽略之.你可以对 " * " (假设这个 “* ”的坐标是 (i, j))画圈,每个圈只能把它四周的某一个点括住(或者是上面(i-1, j) or 下面(i+1, j) or 左边(i, j-1)  or 右边(i, j+1))

poj 1469 COURSES 解题报告

题目链接:http://poj.org/problem?id=1469 题目意思:略 for 循环中遍历的对象要特别注意,究竟是遍历课程数P 还是 学生数N,不要搞混! 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 300 + 5; 7 int match[maxn], map[maxn][maxn];

poj 1789 Truck History 解题报告

题目链接:http://poj.org/problem?id=1789 题目意思:给出 N 行,每行7个字符你,统计所有的 行 与 行 之间的差值(就是相同位置下字母不相同),一个位置不相同就为1,依次累加.问最终的差值最少是多少. 额.....题意我是没看懂啦= =......看懂之后,就转化为最小生成树来做了.这是一个完全图,即每条边与除它之外的所有边都连通.边与边的权值是通过这个差值来算出来的. 1 #include <iostream> 2 #include <cstdio>

poj 1860 Currency Exchange 解题报告

题目链接:http://poj.org/problem?id=1860 题目意思:给出 N 种 currency, M种兑换方式,Nick 拥有的的currency 编号S 以及他的具体的currency(V).M 种兑换方式中每种用6个数描述: A, B, Rab, Cab, Rba, Cba.其中,Rab: 货币A 兑换 货币B 的汇率为Rab,佣金为Cab.Rba:货币B 兑换 货币 A 的汇率,佣金为Cba.假设含有的A货币是x,那么如果兑换成B,得到的货币B 就是:(x-Cab) *

poj 2531 Network Saboteur 解题报告

题目链接:http://poj.org/problem?id=2531 题目意思:将 n 个点分成两个部分A和B(也就是两个子集啦), 使得子集和最大(一定很难理解吧,呵呵).举个例子吧,对于样例,最佳的分法就是把点2分为一个子集,另一个子集理所当然就是1.3了. 2-1 的权值是50,2-3的权值是40,那么最大就是50+40 = 90了. 首先dfs的话,我不太会做啦.看了队长的用了状态压缩来做,一下子觉得好神奇!!!! 可能第一次接触,理解得不是太深刻,先留着吧.就觉得好神奇,好神奇...