UVA 10118-Free Candies
阿新 • • 發佈:2018-12-13
題目大意:
有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裡面的內容,倒是更像暴搜吶,剪枝的暴搜;