• 几个相似的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
    ", 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
    ", 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;
        
    }

     继续努力吧!!

      

  • 相关阅读:
    Merge Intervals
    Jump Game
    微信小程序----button组件
    微信小程序----日期时间选择器(自定义精确到分秒或时段)(MUI日期时间)
    禁止搜索引擎抓取robots.txt文件设置方法
    [转载]【转】代码的版权声明怎么写
    微信小程序----picker选择器(picker、省市区选择器)(MUI选择器)
    微信小程序----模板(template)
    nginx安全配置
    微信小程序----icon组件
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/6057075.html
Copyright © 2020-2023  润新知