码迷,mamicode.com
首页 > 其他好文 > 详细

poj 2346 Lucky tickets

时间:2014-10-10 03:56:13      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   使用   ar   for   

题目链接http://poj.org/problem?id=2346

 

思路:

    使用动态规划解法:

    设函数 d( n, x )代表长度为n且满足左边n/2位的和减去右边n/2位的和为x的数的数目。

 将一个长度为n的数看做n个数字 A1, A2....An ( 0 <= Ai <= 9  ),将字符分为两个集合{ A1, A2....An/2 } 与 { An/2+1.....An };

 问题转换为求集合中元素和相等的数目。先从每个集合中选出一个元素,求它们差为a的可能数目,即d( 2, a );

   再求两个集合剩下的元素和的差为 x - a 的数目,即d( n -2, x -a );所以动态递归方程为 d( n, x ) = d( n - 2, x - a ) * d( 2, a );  (-9<=a<=9)

   可以使用记忆搜索求解。

代码:

 

#include <stdio.h>
#include <math.h>
#include <string.h>

const int MAX_N = 11;
int dp[MAX_N][MAX_N];

int d( int n, int x )
{
    if ( dp[n][x] != -1 )
        return dp[n][x];

    if ( n == 2 )
    {
        int sum = 0;
        for ( int a = 0; a <= 9; ++a )
            for ( int b = 0; b <= 9; ++b )
                if (a - b == x) sum++;
                    return dp[n][x] = sum;
    }
    else
    {
        int a, b, sum = 0;

        for ( b = -9; b <= 9; ++b )
        {
            a = x - b;
            if (a >= -9 * (n - 2) / 2 && a <= 9 * (n - 2) / 2)
                sum += d(n - 2, abs(a)) * d(2, abs(b) );
        }
        return dp[n][x] = sum;
    }    
}

int main()
{
    int n;
    long long ans = 0;

    memset(dp, -1, sizeof(dp));

    scanf("%d", &n);
    ans = d(n, 0);
    printf("%lld\n", ans);

    return 0;
}

 

poj 2346 Lucky tickets

标签:style   blog   http   color   io   os   使用   ar   for   

原文地址:http://www.cnblogs.com/tallisHe/p/4014844.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!