zoukankan      html  css  js  c++  java
  • POJ 2346 Lucky tickets(DP,记忆化)

    POJ 2346 Lucky tickets

    题目传送门

    题意:

    定义一个位数为偶数的数为幸运数当且仅当这个数前一半的部分数字之和等于后一半的数字之和,给出一个n,求出有多少个位数小于n的数是幸运数。

    解题过程:

    我们可以比较容易的想到DP,然后我们会发现DP当中我们需要的只是前一半部分或者后一半部分的和不需要具体指导是多少,所以会有很多重复的情况,而如果暴力搜索,那么必然会TLE,所以我们就可以想到记忆化,f[i][j][k]表示枚举到第i位时,前一半部分的和为j,后一半部分的和为k的时候,幸运数字的个数为多少,然后转移的方程就是枚举0~9数字,由(i,j,k)转移到(i+1,j+num,k)或者(i+1,j,k+num)。这样就会避免很多重复的计算了。

    AC代码:

    #pragma GCC optimize (3)
    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    #include <list>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    int n;
    ll f[15][60][60];
    
    ll dfs(int cnt,int ans1,int ans2) {
        if(f[cnt][ans1][ans2]!=-1)return f[cnt][ans1][ans2];
        if(cnt==n*2) {
            if(ans1==ans2)return 1ll;
        else return 0ll;
        }
        ll ans=0;
        for(int i=0;i<=9;i++) {
        if(cnt<n)ans+=dfs(cnt+1,ans1+i,ans2);
        else ans+=dfs(cnt+1,ans1,ans2+i);
        }
        return f[cnt][ans1][ans2]=ans;
    }
    
    int main() {
        scanf("%d",&n);
        n/=2;
        memset(f,-1,sizeof f);
        ll res=dfs(0,0,0);
        printf("%lld
    ",res);
    }

    本人蒟蒻OIer一枚,欢迎加QQ:840776708一起学习蛤。

    「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」
  • 相关阅读:
    HDU6470 ()矩阵快速幂
    O(1)乘法与快速乘O(log)
    imos 学习笔记五 抓拍 c#
    imos 学习笔记四 录像 c#
    imos 学习笔记三 下载指定时间段视频信息 c#
    imos学习笔记二 用户登录c#
    imos学习笔记一 sdk开发环境
    Hbase(nosql)体系结构有基本操作 笔记八
    zookeeper的安装与配置 笔记七
    mapReduce体系结构和各种算法 笔记六
  • 原文地址:https://www.cnblogs.com/Apocrypha/p/9433669.html
Copyright © 2011-2022 走看看