【训练题29:动态规划+滚动数组】Free Candies | UVA10118 | HDU 1514

Free Candies | HDU 1514

难度

− 317 628 -\frac{317}{628} 628317

看 紫 书 上 有 → 找 到 U V A → V J + U V A O J 交 不 上 → 找 到 H D U 原 题 看紫书上有\rightarrow找到UVA\rightarrow VJ+UVAOJ交不上\rightarrow找到HDU原题 UVAVJ+UVAOJHDU
???

题意

  • 给定四个堆,每堆的糖果你只能从顶开始拿。
  • 给你一个篮子,篮子最多装五个糖果。
  • 如果篮子其中有两个糖果编号一样,则你获得一堆糖果,这两个糖果移除篮子
  • 问你:你最多能获得多少堆糖果?

数据范围

每堆大小 n ≤ 40 n\le 40 n40
糖果种类 ≤ 20 \le 20 20

开始的思路

  • 一看:四堆,每堆最多 40 40 40 个,考虑 D P DP DP 的话 状态数 4 0 4 ≈ 2 e 6 40^4\approx2e6 4042e6 貌似可行
  • 然后假设 d p [ i ] [ j ] [ k ] [ p ] dp[i][j][k][p] dp[i][j][k][p] 表示第一堆、第二堆、第三堆、第四堆拿了 i 、 j 、 k 、 p i、j、k、p ijkp个糖时能获得最多多少对糖果。
  • 因为每堆拿的数量一定了,多余的一些没有匹配的在篮子里的糖果也是一定的。
  • 我们把他们存入 V [ i ] [ j ] [ k ] [ p ] V[i][j][k][p] V[i][j][k][p] 中。
  • 状态转移:对于 ( i , j , k , p ) (i,j,k,p) (i,j,k,p)的情况,我们只有四种状态转移过来:
    ( i − 1 , j , k , p ) 、 ( i , j − 1 , k , p ) 、 ( i , j , k − 1 , p ) 、 ( i , j , k , p − 1 ) (i-1,j,k,p)、(i,j-1,k,p)、(i,j,k-1,p)、(i,j,k,p-1) (i1,j,k,p)(i,j1,k,p)(i,j,k1,p)(i,j,k,p1)
  • 转移过来的时候,只要选择一种合法状态转移过来即可,因为能转移的话答案是一定的。
  • 如果四种状态都是非法的(无法达到的状态),那么新的状态也无法达到。

然后的思路

  • 写完快快乐乐交上去,结果因为 M L E MLE MLE 瞬间嗝屁。
  • 内存 O ( k × 4 0 4 ) O(k\times 40^4) O(k×404),这里 k k k 至少也得是 2 2 2吧, 2 × 4 0 4 = 5 e 6 2\times 40^4=5e6 2×404=5e6
  • 给定的内存 32768 K = 32768 ∗ 1024 / 8 ( 个 i n t ) = 4 e 6 ( 个 i n t ) 32768K=32768*1024/8(个int)=4e6(个int) 32768K=327681024/8(int)=4e6(int),明显超了。
  • 考虑到转移只会影响上一层的,我们滚动数组一下!(然后就过了。)

核心代码

时间复杂度: O ( k × 4 0 4 ) O(k\times 40^4) O(k×404)
空间复杂度: O ( k × 4 0 3 ) O(k\times 40^3) O(k×403)
这里大约 1 ≤ k ≤ 5 1\le k\le 5 1k5

/*
 _            __   __          _          _
| |           \ \ / /         | |        (_)
| |__  _   _   \ V /__ _ _ __ | |     ___ _
| '_ \| | | |   \ // _` | '_ \| |    / _ \ |
| |_) | |_| |   | | (_| | | | | |___|  __/ |
|_.__/ \__, |   \_/\__,_|_| |_\_____/\___|_|
        __/ |
       |___/
*/
const int MAX = 1e6+50;
const int INF = 0x3f3f3f3f;

int aa[50][6];
vector<int>V[3][41][41][41];
int dp[3][41][41][41];
int main()
{
    
    
    int n;
    while(~scanf("%d",&n)){
    
    
        if(n == 0)break;
        for(int i = 1;i <= n;++i){
    
    
            for(int j = 1;j <= 4;++j){
    
    
                scanf("%d",&aa[i][j]);
            }
        }
        for(int i = 0;i <= 2;++i)
        for(int j = 0;j <= n;++j)
        for(int k = 0;k <= n;++k)
        for(int p = 0;p <= n;++p){
    
    
            V[i][j][k][p].clear();
        }

        int ans = 0;
        for(int i = 0;i <= n;++i)
        for(int j = 0;j <= n;++j)
        for(int k = 0;k <= n;++k)
        for(int p = 0;p <= n;++p){
    
    
            int t = (i-1+3)%3;

            V[i%3][j][k][p].clear();
            dp[i%3][j][k][p] = 0;

            if(i && V[t][j][k][p].size() < 5){
    
    
                dp[i%3][j][k][p] = dp[t][j][k][p];
                bool fd = false;
                for(auto it : V[t][j][k][p]){
    
    
                    if(it == aa[i][1])fd = true;
                    else V[i%3][j][k][p].push_back(it);
                }
                if(!fd)V[i%3][j][k][p].push_back(aa[i][1]);
                else dp[i%3][j][k][p]++;
            }else if(j && V[i%3][j-1][k][p].size() < 5){
    
    
                dp[i%3][j][k][p] = dp[i%3][j-1][k][p];
                bool fd = false;
                for(auto it : V[i%3][j-1][k][p]){
    
    
                    if(it == aa[j][2])fd = true;
                    else V[i%3][j][k][p].push_back(it);
                }
                if(!fd)V[i%3][j][k][p].push_back(aa[j][2]);
                else dp[i%3][j][k][p]++;
            }else if(k && V[i%3][j][k-1][p].size() < 5){
    
    
                dp[i%3][j][k][p] = dp[i%3][j][k-1][p];
                bool fd = false;
                for(auto it : V[i%3][j][k-1][p]){
    
    
                    if(it == aa[k][3])fd = true;
                    else V[i%3][j][k][p].push_back(it);
                }
                if(!fd)V[i%3][j][k][p].push_back(aa[k][3]);
                else dp[i%3][j][k][p]++;
            }else if(p && V[i%3][j][k][p-1].size() < 5){
    
    
                dp[i%3][j][k][p] = dp[i%3][j][k][p-1];
                bool fd = false;
                for(auto it : V[i%3][j][k][p-1]){
    
    
                    if(it == aa[p][4])fd = true;
                    else V[i%3][j][k][p].push_back(it);
                }
                if(!fd)V[i%3][j][k][p].push_back(aa[p][4]);
                else dp[i%3][j][k][p]++;
            }else{
    
    
                if(i || j || k || p)for(int tmp = 1;tmp <= 6;++tmp)V[i%3][j][k][p].push_back(-1);
            }
            
            if(V[i%3][j][k][p].size() <= 5){
    
    
                ans = max(ans,dp[i%3][j][k][p]);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45775438/article/details/112795974