• 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一起学习蛤。

    「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」
  • 相关阅读:
    mysql查询数据返回touple改为字典的方法
    win32api 获取文件版本信息
    LINK : fatal error LNK1104: 无法打开文件“gtestd.lib”
    gtest vs2015配置
    Akka Quickstart with Java-笔记
    Linux下tar压缩解压缩命令详解
    Hadoop Streaming开发要点
    Hadoop Steaming开发之WordCount
    hadoop常见问题
    Java中通过脚本引擎调用js函数
  • 原文地址:https://www.cnblogs.com/Apocrypha/p/9433669.html
Copyright © 2020-2023  润新知