题意
4堆糖果,每堆 n 颗,每次拿最顶上的,篮子里能装5颗糖果,拿到两颗一样的就可以拿走,求最多能拿走多少颗。
解析
可用记忆化搜索。
用一个bitset(或bool数组)存储当前拿走的糖果颜色,如果拿糖果时已经拿过同颜色的可以将bitset相应位清零。
用一个数组(函数参数也行)存储当前第 i 堆拿走的个数。
返回时将当前状态(每堆拿了几个)记录下来,再次搜索时直接返回。
别忘了每次输入时清空数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <algorithm> #include <iostream> #include <cstring> #include <bitset> using namespace std; int n,arr[50][5],mem[50][50][50][50],top[5]; bitset<50> take; int dfs(int num){ if(mem[top[0]][top[1]][top[2]][top[3]]!=-1) return mem[top[0]][top[1]][top[2]][top[3]]; if(num==5) return mem[top[0]][top[1]][top[2]][top[3]] = 0; int res=0; for(int i=0;i<4;i++){ if(top[i]==n) continue; int c = arr[top[i]][i]; take[c] = !take[c]; top[i]++; if(take[c]){ res = max(res,dfs(num+1)); }else{ res = max(res,dfs(num-1)+1); } take[c] = !take[c]; top[i]--; } return mem[top[0]][top[1]][top[2]][top[3]] = res; } int main(){ while(cin >> n && n!=0){ memset(arr,0,sizeof(arr)); memset(mem,-1,sizeof(mem)); memset(top,0,sizeof(top)); take = 0; for(int i=0;i<n;i++){ cin >> arr[i][0] >> arr[i][1] >> arr[i][2] >> arr[i][3]; } cout << dfs(0) << endl; } return 0; }
|