原题:
Little Bob is playing a game. He wants to win some candies in it - as many as possible.
There are 4 piles, each pile contains N candies. Bob is given a basket which can hold at most 5
candies. Each time, he puts a candy at the top of one pile into the basket, and if there’re two candies of the same color in it, he can take both of them outside the basket and put them into his own pocket. When the basket is full and there are no two candies of the same color, the game ends. If the game is played perfectly, the game will end with no candies left in the piles.
For example, Bob may play this game like this (N = 5):

Note that different numbers indicate different colors, there are 20 kinds of colors numbered 1..20.
‘Seems so hard…’ Bob got very much puzzled. How many pairs of candies could he take home at most?
Input
The input will contain not more than 10 test cases. Each test case begins with a line containing a single integer n(1 ≤ n ≤ 40) representing the height of the piles. In the following n lines, each line contains four integers x i 1 , x i 2 , x i 3 , x i 4 (in the range 1..20). Each integer indicates the color of the corresponding candy. The test case containing n = 0 will terminate the input, you should not give an answer to this case.
Output
Output the number of pairs of candies that the cleverest little child can take home. Print your answer in a single line for each test case.
Sample Input
5
1 2 3 4
1 5 6 7
2 3 3 3
4 9 8 6
8 7 2 1
1
1 2 3 4
3
1 2 3 4
5 6 7 8
1 2 3 4
0
Sample Output
8
0
3

中文:
给你4堆糖果,然后给你一个能容纳5个糖的篮子。每次在你篮子里面有两个相同的糖果的时候你就可以把篮子当中的这对糖果放到自己兜里,问你最多可以放兜里多少个?

#include <bits/stdc++.h>
using namespace std;
int dp[41][41][41][41],n;
int candy[41][41],ans;
bool mark[21];
bool vis[41][41][41][41];
int get_num()
{int cnt=0;for(int i=1;i<=20;i++)if(mark[i])cnt++;return cnt;
}
int get_candy(int r,int c)
{return candy[r][c];
}
int dfs(int i,int j,int k,int w)
{if(vis[i][j][k][w])return dp[i][j][k][w];int Max=0;if(get_num()<5){if(i+1<=n){int can=get_candy(i+1,1);if(mark[can]){mark[can]=0;Max=max(Max,dfs(i+1,j,k,w)+1);mark[can]=1;}else{mark[can]=1;Max=max(Max,dfs(i+1,j,k,w));mark[can]=0;}}if(j+1<=n){int can=get_candy(j+1,2);if(mark[can]){mark[can]=0;Max=max(Max,dfs(i,j+1,k,w)+1);mark[can]=1;}else{mark[can]=1;Max=max(Max,dfs(i,j+1,k,w));mark[can]=0;}}if(k+1<=n){int can=get_candy(k+1,3);if(mark[can]){mark[can]=0;Max=max(Max,dfs(i,j,k+1,w)+1);mark[can]=1;}else{mark[can]=1;Max=max(Max,dfs(i,j,k+1,w));mark[can]=0;}}if(w+1<=n){int can=get_candy(w+1,4);if(mark[can]){mark[can]=0;Max=max(Max,dfs(i,j,k,w+1)+1);mark[can]=1;}else{mark[can]=1;Max=max(Max,dfs(i,j,k,w+1));mark[can]=0;}}}else{vis[i][j][k][w]=1;dp[i][j][k][w]=0;return 0;}dp[i][j][k][w]=Max;vis[i][j][k][w]=true;ans=max(ans,Max);return dp[i][j][k][w];
}int main()
{ios::sync_with_stdio(false);while(cin>>n,n){for(int i=1;i<=n;i++)for(int j=1;j<=4;j++)cin>>candy[i][j];memset(dp,0,sizeof(dp));memset(vis,0,sizeof(vis));ans=-1;dfs(0,0,0,0);cout<<ans<<endl;}return 0;
}

解答:
这题倒是挺好想,可惜代码不是很好布置。考虑记忆化搜索,还有记录并回溯上一次的状态,这点很不好弄。
那么,一般这种题可以考虑利用引用或者指针来帮助实现。
首先先考虑搜索问题,那么一共可以搜四个状态,分别就是拿第一堆,第二堆,第三堆,第四堆最上面的。如何下来,应该是一个四叉树,那么如何优化呢?考虑,背包问题用记忆化搜索时,是避免搜索重复的子状态,而用dp(….)数组进行保存状态,那么这道题的过程当中有没有重复的子状态?有!
如图

其中,黑色的竖线代表每堆糖果,短一点的代表少了一个,如此枚举下来,肯定会有重复的状态(把绿色的圈补全就能看到),所以用dp[i][j][k][w]记录当前状态的最优值即可。题目当中还有一个要求,那就是篮子的大小是5,所以要设定一个mark数组用来记录手里有的糖果类型,注意这里的糖果类型本来应该是作为动态规划中新增加的一个维度出现的,也就是新增加的一个状态,类似dp[i][j][k][w][S]其中S代表手里的糖果种类,但是考虑到内存的原因,所以只能单独拿出来,所以在枚举状态的过程中要用到回溯来解决。篮子中糖的数量可以查看mark即可。
转移方程就是dp[i][j][k][w]=max(dp[i+1][j][k][w],dp[i][j+1][k][w],dp[i][j][k+1][w],dp[i][j][k][w+1])+2 (当前i,j,k,w状态的mark中存在第i+1,j+1,k+1,w+1同类型的糖,且篮子的数量不超过5)

uva 10118 Free Candies相关推荐

  1. UVA - 10118 Free Candies 记忆化搜索

    题目链接:UVA - 10118 题目是PDF就不贴了,大意就是有四堆糖果,每堆有n个,有个人有个能盛五个糖的篮子,每次可以任选一堆糖,取最上面的那个放到篮子里,如果篮子里有两个颜色相同的,就可以把这 ...

  2. uva 10118 - Free Candies(记忆化搜索)

    题目大意:10118 - Free Candies 题目大意:有4堆糖果, 每堆糖果有n颗糖果,然后给出每颗糖果的类型1~20,然后只有取走当前堆的前面一颗糖果后才可以取后面的糖果, 然后小伙伴有一个 ...

  3. UVA - 10118 Free Candies

    题目链接:https://vjudge.net/problem/UVA-10118 Little Bob is playing a game. He wants to win some candies ...

  4. UVA - 10118 Free Candies 记忆化搜索经典

    思路:d[a][b][c][d]表示从已经第一个篮子取了a颗糖,第二个取了b颗糖,第三个取了c颗糖,第四个取了d颗糖最多还能够获得多少糖果.首先明白一个问题:如果能分别取a,b,c,d个,不论如何取, ...

  5. uva 10118 ——Free Candies

    题意:桌子上有4 堆糖果,要从这四堆糖果中取出5个,如果5个中有相同的颜色则把他们拿出来放到口袋,求最多放多少糖果. 思路:DAG最长路问题.需要把问题转化成DAG的问题,以个数作为转移的状态,当达到 ...

  6. UVA 10118 Free Candies

    UVA_10118 我们可以定义f[n1][n2][n3][n4]为当四个piles分别拿到第n1.n2.n3.n4个糖果时,能够拿回家的最多的pair数,然后在状态转移的时候需要借助一个数组来记录b ...

  7. UVA - 10118 Free Candies(记忆化搜索/状压)

    传送门 方法一 一开始我确实是这样想的,设d[i][j][k][p][S]d[i][j][k][p][S]d[i][j][k][p][S]为四堆分别拿了i,j,k,pi,j,k,pi,j,k,p个,当 ...

  8. Free Candies UVA - 10118

    题目:B - Free Candies UVA - 10118 题意: 桌上有4堆糖果,每堆糖果高度不超过40,每颗糖果有一种颜色(一共20种,1,2,3...,20), 有一个篮子,一开始是空的,每 ...

  9. uva 10118(DP)

    UVA 10118 题意: 有4堆糖果,每堆有n(最多40)个,有一个篮子,最多装5个糖果,我们每次只能从某一堆糖果里拿出一个糖果, 如果篮子里有两个相同的糖果,那么就可以把这两个(一对)糖果放进自己 ...

最新文章

  1. jQuery 设置select默认选中问题
  2. 新闻发布系统类图_如何熟悉一个系统?(内含知识大图)
  3. 前端 html结合css-1篇
  4. 驱动框架5——基于驱动框架写led驱动
  5. 【PL/SQL】学习笔记 (1)一个简单的PL/SQL程序
  6. html 表单js验证,JavaScript使用表单元素验证表单
  7. 计算机辅助管理与制造,计算机辅助设计与制造,对产品的设备进行管理,完成产品加工制造...
  8. Compiler__visual_studio_2010_pro 激活码
  9. 以V神为灵感创作的加密艺术NFT“EthBoy”以260ETH高价售出
  10. java 中文字符串 排序_Java实现对中文字符串的排序功能实例代码
  11. html动画转换为桌面动态壁纸,怎么设置电脑动态壁纸-动态桌面,这个功能太好玩了...
  12. java 调用图灵接口_图灵机器人(问答机器人)API调用示例
  13. 码分复用:为什么可以通过收到的码片序列与站的序列做内积的值判断每个站是否发送数据及数据值
  14. 潘石屹陈志武谈房地产:北京等城市泡沫已很严重(载自新浪)
  15. 城市生态类毕业论文文献有哪些?
  16. 视频教程-OpenGLES萌谷手册(iOS2018版)-其他
  17. Java基础练习:用户在控制台输入一个年份,判断该年份是平年还是闰年
  18. 【MySQL 8.0 OCP 1Z0-908认证考试】题库精讲--第五讲mysqlbinlog与mysqldump(上)
  19. 性能领域:你知道的越多,不知道的也就越多
  20. 举安全之盾,防事故之患

热门文章

  1. sql 删除唯一索引unique
  2. 云计算的认识和看法_个人对云计算的看法 我对云计算的认识
  3. 51nod 2455 花园
  4. Android结束进程的几种方法
  5. CAN总线终端电阻的作用
  6. HTML+CSS聚光灯效果动画
  7. IAR for ARM系列教程(二)_主窗口与工具栏的描述
  8. 【模型压缩】Channel Pruning for Accelerating Very Deep Neural Networks算法笔记
  9. php 抓取 知乎专栏,php爬取知乎用戶信息
  10. VBA操作WORD(三):设置页面