zoukankan      html  css  js  c++  java
  • hdu 1514 Free Candies 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1514

    题目意思:有4堆糖果,每堆糖果有n个,从上到下排好,取糖果只能从上往下取,取完的糖果放在篮子里,篮子里最多放5个,如果篮子里有两个颜色相同的糖果则可以取走放进口袋里,问最多能取走多少对糖果放进口袋。n<=40, 糖果颜色最多20种。

         这题是抄这个人滴:http://fudq.blog.163.com/blog/static/1913502382014239225290/

         有些地方看得不太懂,本来想搜状态压缩DP来体会下的,阴差阳错、迷迷糊糊找到了这题= =.......可能水平不太够啦,先留着吧.......能理解到的我都写注释了,不能理解的打了个“?”

         只能说,DP好抽象啊,泪 >_< ,慢慢来吧,继续努力!!!

        

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <set>
     6 using namespace std;
     7 
     8 const int candy_num = 40 + 5;
     9 const int basket_num = 5 + 2;
    10 
    11 // dp[i][j][k][l]: 四个糖堆分别拿走了几个
    12 //  第1个pile被取走i个,第2个pile被取走j个,第3个pile被取走k个,第4个pile被取走l个时pocket能装入的candy数
    13 // h[i]:记录第i个糖堆被取走了多少糖果
    14 int dp[candy_num][candy_num][candy_num][candy_num];
    15 int h[basket_num], f[candy_num][basket_num];
    16 int ans, n;
    17 
    18 set<int> S;
    19 set<int> ::iterator it;
    20 
    21 int check(int a)
    22 {
    23     it = S.find(a);
    24     if (it != S.end())   // basket里面有颜色跟当前颜色(a)相同的糖果,从basket里拿出
    25     {
    26         S.erase(a);
    27         return 1;
    28     }
    29     S.insert(a);   // basket中没有a这种颜色,放入basket中
    30     return 0;
    31 }
    32 
    33 int dfs(int tmp)
    34 {
    35     if (dp[h[0]][h[1]][h[2]][h[3]] != -1)   // 这个状态搜过
    36         return dp[h[0]][h[1]][h[2]][h[3]];
    37     int tt = 0;
    38     for (int i = 0; i < 4; i++)   // 从四个basket中拿糖果
    39     {
    40         if (h[i] < n && S.size() < 5)
    41         {
    42             int t = check(f[h[i]][i]);
    43             if (S.size() < 5)
    44             {
    45                 h[i]++;   // 第i个pile里被取走一个candy
    46                 tt = max(tt, dfs(tmp+t));   // ?
    47                 h[i]--;
    48             }
    49             tt = max(tt, tmp+t);     // ?
    50             if (t == 1)               
    51                 S.insert(f[h[i]][i]);
    52             else
    53                 S.erase(f[h[i]][i]);
    54         }
    55     }
    56     return dp[h[0]][h[1]][h[2]][h[3]] = tt;
    57 }
    58 
    59 int main()
    60 {
    61     while (scanf("%d", &n) != EOF && n)
    62     {
    63         for (int i = 0; i < n; i++)
    64         {
    65             for (int j = 0; j < 4; j++)
    66                 scanf("%d", &f[i][j]);
    67         }
    68 /*        for (int i = 0; i < n; i++)
    69         {
    70             for (int j = 0; j < 4; j++)
    71                 printf("f[%d][%d] = %d
    ", i, j, f[i][j]);
    72         }
    73 */
    74         ans = 0;
    75         h[0] = h[1] = h[2] = h[3] = 0;
    76         memset(dp, -1, sizeof(dp));
    77         printf("%d
    ", dfs(0));
    78     //    printf("dp[%d][%d][%d][%d] = %d
    ", h[0], h[1], h[2], h[3], dp[h[0]][h[1]][h[2]][h[3]]);
    79     }
    80     return 0;
    81 }

         

         

  • 相关阅读:
    20.12.21 leetcode316
    20.12.18 leetcode389
    NOIP2017退役记
    DNA序列 LOJ NOIP模拟赛 D1T1 字符串哈希
    解药还是毒药 codevs2594 状态压缩 BFS
    换教室 vijos2005 NOIP2016 D1T3 期望DP 图论最短路(雾)
    都市大飙车 UESTC 1652 概率DP
    添加括号 vijos1038 动态规划 区间DP
    一道神奇的并查集
    还有一道神奇的暴力(正解是要旋转坐标轴的)
  • 原文地址:https://www.cnblogs.com/windysai/p/3895884.html
Copyright © 2011-2022 走看看