1. 程式人生 > >UVA 10118-Free Candies

UVA 10118-Free Candies

題目連結

題目大意:

      有4堆糖果,每一堆有n個糖果,有一個籃子,這個籃子的最大容量為5塊糖,每一次從這四堆中選擇一堆,然後將最上面的糖果拿下來,放到籃子裡面去,如果有相同兩塊糖的就把這;兩塊糖拿出來,如果達到了5塊糖,並且這5塊糖是兩兩不相同的就結束遊戲,問你,最多能拿出多少對對對對糖

變形的記憶化搜尋!!!

Code:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
const int maxn = 45;
int num[maxn][4];                     //存放輸入的數字
int top[4];                           //現在每一堆拿到第幾個了
int dp[maxn][maxn][maxn][maxn];       //遞推,記錄結果的陣列
int vis[4*maxn];                      //記錄籃子裡有沒有現在這個數字
int n;


int DP(int k)
{
    int & ans = dp[top[0]][top[1]][top[2]][top[3]];
    if(ans != -1)   return ans;
    ans = 0;
    if(k >= 5)      return ans;         //籃子裡面最多有5個,如果有5個不一樣的就退出
    for(int i = 0; i < 4; i++){
        if(top[i] == n)  continue;      //這一堆已經全部都拿完了
        ++top[i];
        if(vis[num[top[i]][i]]){           //在籃子裡面有一樣的
            vis[num[top[i]][i]] = false;   //把一樣的拿出去
            ans = max(ans, DP(k-1)+1);     //  !!!!!
            vis[num[top[i]][i]] = true;    //恢復原樣
        }
        else{
            vis[num[top[i]][i]] = true;
            ans = max(ans, DP(k+1));     //   !!!!
            vis[num[top[i]][i]] = false;
        }
        --top[i];
    }
    return ans;
}


int main()
{
    while(scanf("%d", &n) && n){
        for(int i = 1; i <= n; i++){
            for(int j = 0; j < 4; j++)
                scanf("%d", &num[i][j]);
        }
        memset(top, 0, sizeof(top));
        memset(dp, -1, sizeof(dp));
        memset(vis, false, sizeof(vis));
        printf("%d\n", DP(0));
    }
    return 0;
}




怎麼感覺記憶化搜尋不怎麼像DP裡面的內容,倒是更像暴搜吶,剪枝的暴搜;