几个相似的DP题

  HDU1398

  题意:把一个整数分拆成1、4、9、16、……、256、289(注意:只到289)这17个完全平方数的和,有几种方法。

  解法不用说自然是DP,因为搜索显然超时。

  (这样的题我一般不敢开int,怕爆……)

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <functional>
 6
 7 using namespace std;
 8
 9 #define REP(i,n)        for(int i(0); i <  (n); ++i)
10 #define rep(i,a,b)        for(int i(a); i <= (b); ++i)
11 #define dec(i,a,b)        for(int i(a); i >= (b); --i)
12 #define for_edge(i,x)        for(int i = H[x]; i; i = X[i])
13
14 #define LL    long long
15 #define ULL    unsigned long long
16 #define MP    make_pair
17 #define PB    push_back
18 #define FI    first
19 #define SE    second
20 #define INF    1 << 30
21
22 const int N    =    100000        +    10;
23 const int M    =    10000        +    10;
24 const int Q    =    1000        +    10;
25 const int A    =    30        +    1;
26
27 LL f[Q];
28 int n;
29
30
31 int main(){
32 #ifndef ONLINE_JUDGE
33     freopen("test.txt", "r", stdin);
34     freopen("test.out", "w", stdout);
35 #endif
36
37
38     memset(f, 0, sizeof f);
39     f[0] = 1LL;
40     rep(i, 1, 17) rep(j, 0, 305)
41         f[j + i * i] += f[j];
42
43     while (~scanf("%d", &n), n) printf("%lld\n", f[n]);
44
45
46     return 0;
47
48 }

  HDU1028 自然数无序拆分  

  恩,经典的DP题

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <functional>
 6
 7 using namespace std;
 8
 9 #define REP(i,n)        for (int i(0); i < (n); ++i)
10 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
11 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
12
13 #define LL    long long
14 #define ULL   unsigned long long
15 #define MP    make_pair
16 #define FI    first
17 #define SE    second
18
19 const int INF  =    1000000;
20 const int M    =    10000    +    10;
21 const int N    =    200    +    10;
22 const int A    =    3000    +    1;
23
24
25 int f[N][N];
26 int n;
27
28 int main(){
29     freopen("1test.in", "r", stdin);
30     freopen("1test.out", "w", stdout);
31
32     rep(i, 1, 150) f[1][i] = 1, f[i][1] = 1;
33     rep(i, 1, 150) rep(j, 1, 150){
34         if (j > i) f[i][j] = f[i][i]; else
35         if (i == j) f[i][j] = f[i][j - 1] + 1; else
36         f[i][j] = f[i][j - 1] + f[i - j][j];
37     }
38
39     while (~scanf("%d ", &n)) printf("%d\n", f[n][n]);
40
41     return 0;
42
43 }

   二维的方法……但是我以前用一维的方法AC过,总觉得该回忆起来……

  HDU5890  去掉给定编号的三个数(如果有编号重复那就相当于去掉了两个数甚至一个数)任意选10个数,相加,是否可以得到87?

  当初青岛网赛的题,题意不难理解就是A不掉。

  后来查了很多资料,并且看了很多巨屌的博客。我终于得出一个结论:此题要用bitset优化。

  思想也是背包,但是和前两道比起来就比较复杂了。

  

#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define rep(i,a,b)        for(int i(a); i <= (b); ++i)
#define dec(i,a,b)        for(int i(a); i >= (b); --i)

const int N    =    50        +    2;

int T;
int q;
int f[N][N][N];
int n;
int c[5];
int a[N];
int Q;

bitset <90> A[12];

int check(int i, int j, int k){
    rep(h, 0, 10) A[h].reset(); A[0][0] = 1;
    rep(h, 1, n) if (h != i && h != j && h != k && a[h] <= 87) dec(p, 9, 0){
        A[p + 1] |= A[p] << a[h];
        if (A[10][87]) return 1;
    }

    return 0;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.txt", "r", stdin);
    freopen("test.out", "w", stdout);
#endif

    scanf("%d", &T);
    while (T--){
        scanf("%d", &n);
        rep(i, 1, n) scanf("%d", a + i);
        rep(i, 1, n) rep(j, i, n) rep(k, j, n) f[i][j][k] = check(i, j, k);
        scanf("%d", &Q);
        while (Q--){
            scanf("%d%d%d", c + 1, c + 2, c + 3);
            sort(c + 1, c + 4);
            puts(f[c[1]][c[2]][c[3]] ? "Yes" : "No");
        }
    }

    return 0;

}

继续努力吧!!

  

时间: 2024-10-24 10:04:27

几个相似的DP题的相关文章

ACM/ICPC算法训练 之 数学很重要-浅谈“排列计数” (DP题-POJ1037)

这一题是最近在看Coursera的<算法与设计>的公开课时看到的一道较难的DP例题,之所以写下来,一方面是因为DP的状态我想了很久才想明白,所以借此记录,另一方面是看到这一题有运用到 排列计数 的方法,虽然排列计数的思路简单,但却是算法中一个数学优化的点睛之笔. Poj1037  A decorative fence 题意:有K组数据(1~100),每组数据给出总木棒数N(1~20)和一个排列数C(64位整型范围内),N个木棒长度各异,按照以下条件排列,并将所有可能结果进行字典序排序 1.每一

2014 HDU多校弟九场I题 不会DP也能水出来的简单DP题

听了ZWK大大的思路,就立马1A了 思路是这样的: 算最小GPA的时候,首先每个科目分配到69分(不足的话直接输出GPA 2),然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到100即可 算最大GPA的时候,首先每个科目分配到60分,然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到85即可,如果还有REMAIN POINT,就FOR循环下来加到100上限即可 不会DP 阿 QAQ 过段时间得好好看DP了  =  = 于是默默的把这题标记为<水题集> //

HDU 2577 How to Type(dp题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2577 解题报告:有一个长度在100以内的字符串,并且这个字符串只有大写和小写字母组成,现在要把这些字符串用键盘输入到电脑中,一开始的时候大写锁定是关闭的,并且要求结束的时候也是关闭的,然后让你求输入这些字符串最少需要按多少次键盘(包括Cap Lock键和Shift键) 一个典型的dp题,定义一个一维数组就够了,然后dp[i]的含义的输入到第i个字符时需要按键的最少次数.然后递推公式如下: dp[i]

4815 江哥的dp题a

4815 江哥的dp题a 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 给出一个长度为N的序列A(A1,A2,A3,...,AN).现选择K个互不相同的元素,要求: 1.两两元素互不相邻 2.元素值之和最大 输入描述 Input Description 第一行两个正整数N,K. 接下来一行N个整数,描述A. 输出描述 Output Description 输出一行一个整数,描述答案(最大和). 样例输入 Sample I

(计数器)NOIP模拟赛(神奇的数位DP题。。)

没有原题传送门.. 手打原题QAQ [问题描述]     一本书的页数为N,页码从1开始编起,请你求出全部页码中,用了多少个0,1,2,-,9.其中-个页码不含多余的0,如N=1234时第5页不是0005,只是5. [输入]        一个正整数N(N≤109),表示总的页码. [输出]        共十行:第k行为数字k-1的个数. 这道题是一道很有意思的DP题. 我们先来看一看这道题目 就是求1~n这么多个数中有多少个X数字. 然后我们来看一看一个例子: 在1~10这10个数中,每个数

从一道简单的dp题中学到的...

今天想学点动态规划的知识,于是就看了杭电的课件,数塔问题啊,LCS啊都是比较经典的动规了,然后随便看了看就开始做课后练习题... HDOJ 1421 搬寝室 http://acm.hdu.edu.cn/showproblem.php?pid=1421 题目大意:从n(n <= 2000)个数中选出k对数(即2*k个),使它们的差的平方和最小. 例如:从8,1,10,9,9中选出2对数,要使差的平方和最小,则应该选8和9.9和10,这样最小,结果为2 因为知道是dp的题,先建个dp[][]数组,然

杭电dp题集,附链接

Robberies 点击打开链接 背包;第一次做的时候把概率当做背包(放大100000倍化为整数):在此范围内最多能抢多少钱  最脑残的是把总的概率以为是抢N家银行的概率之和- 把状态转移方程写成了f[j]=max{f[j],f[j-q[i].v]+q[i].money}(f[j]表示在概率j之下能抢的大洋); 正确的方程是:f[j]=max(f[j],f[j-q[i].money]*q[i].v)  其中,f[j]表示抢j块大洋的最大的逃脱概率,条件是f[j-q[i].money]可达,也就是

飞扬的小鸟(NOIP2014)(丧病DP题)

原题传送门 刚开始我还以为这道题目非常的简单.. 然后随便打了一个DP,直接WA,被zxyer狠狠地D了一顿. 然后发现有好多细节.. 首先假如某横坐标没有管子,那么l[x]=0;h[x]=m+1; 然后DP的时候往上是完全背包,往下是01背包. 由于不能接触到管子,所以0~l[x]和h[x]~m要设值inf方便下面判断. m-max(q)*x[i]~m也要特判,因为有限高.. 最后统计答案也是很醉... 下面贴代码.. #include<iostream> #include<cstdi

回顾一些较简单的dp题

1.导弹拦截  (+贪心) 两问:一个导弹拦截系统最多能拦多少导弹 要拦截所有导弹至少需要多少拦截系统 第一问感觉是一个比较巧妙的方法: 维护一个单调递减的序列 length[] 记录的是拦截导弹的高度 当下一个导弹小于 length[] 最后一个数(最小的数)则直接把它加在序列后即可 若大于 则找到序列中比它大的最小的数(二分)然后替换 可以保证最优 第二问 就是贪心啊 当现有的导弹系统的拦截高度都小于当前导弹的高度 则开一个新的系统 否则找到拦截高度比导弹高度高的最小的系统来拦截 这里记录系