LightOJ(1422)——Halloween Costumes
2015-08-28 17:55
190 查看
首先,我还是表扬一下自己,开始独立思考了,虽然说最后的想法是错误的,但是至少已经很接近了。所以,再接再厉吧!
题意:
现在那个人要去参加一个聚会,然后总共有n天,每天所要求穿的服饰的序号分别为c[i]。
这个人可以一次性穿上1件衣服,或者一次性脱下任意多件衣服。当然也可以在衣服外面套衣服。
并且如果这件衣服已经被脱下的话,那么它下次不能再次被穿上,如果我们还需要这件衣服的话,那么我们就只能重新再去买另外一件了。
最后问你,如果要参加完所有的派对,那么他所需要的最少的衣服数量是多少。
比如说第一个样例:
4
1 2 1 2
我们只需要先穿上1,然后再穿上2,再脱掉1,然后此时没有2的衣服了,所以我们还需要一件2的衣服,所以最后总共是需要3件衣服。
思路:
这题主要的难点是在于判断什么时候可以利用还存在的衣服。
定义dp[i][j]为i~j区间内所需要的最少衣服的数量。
感觉下面的思路很巧妙:
为什么从后面往前面推呢,我感觉就像是01背包为什么从后面往前面推一样,防止前面的影响后面的,(但是这里说实话我自己也不是很明白)所以我们这里进行倒着for。
1)dp[i][i]=1,这是初始化dp
2)当我们把第s件衣服单独拎出来的时候,那么就是dp[s][e]=dp[s+1][e]+1; 后面加1是因为这里还要多选1件。
3)然后枚举中间点k,当c[s]==c[k]时,这里的意思 是到第k天为止都穿着第i天的衣服,那么dp[s][e]=min(dp[s][e],dp[s+1][k-1]+dp[k][e]); 后面那个式子是因为我们这里不选择s这件衣服了,至于为什么要枚举到第k-1是因为,万一后面k~e区间中还存在c[k]==c[?],那么我们dp[k][e]就是要在这里面取最优的结果的,所以第一个区间是到k-1为止的。
推荐几个好懂的博客:http://www.cnblogs.com/neopenx/p/4050003.html http://www.cnblogs.com/kuangbin/archive/2013/04/29/3051392.html
http://www.cnblogs.com/ziyi--caolu/archive/2013/08/04/3236035.html
题意:
现在那个人要去参加一个聚会,然后总共有n天,每天所要求穿的服饰的序号分别为c[i]。
这个人可以一次性穿上1件衣服,或者一次性脱下任意多件衣服。当然也可以在衣服外面套衣服。
并且如果这件衣服已经被脱下的话,那么它下次不能再次被穿上,如果我们还需要这件衣服的话,那么我们就只能重新再去买另外一件了。
最后问你,如果要参加完所有的派对,那么他所需要的最少的衣服数量是多少。
比如说第一个样例:
4
1 2 1 2
我们只需要先穿上1,然后再穿上2,再脱掉1,然后此时没有2的衣服了,所以我们还需要一件2的衣服,所以最后总共是需要3件衣服。
思路:
这题主要的难点是在于判断什么时候可以利用还存在的衣服。
定义dp[i][j]为i~j区间内所需要的最少衣服的数量。
感觉下面的思路很巧妙:
为什么从后面往前面推呢,我感觉就像是01背包为什么从后面往前面推一样,防止前面的影响后面的,(但是这里说实话我自己也不是很明白)所以我们这里进行倒着for。
1)dp[i][i]=1,这是初始化dp
2)当我们把第s件衣服单独拎出来的时候,那么就是dp[s][e]=dp[s+1][e]+1; 后面加1是因为这里还要多选1件。
3)然后枚举中间点k,当c[s]==c[k]时,这里的意思 是到第k天为止都穿着第i天的衣服,那么dp[s][e]=min(dp[s][e],dp[s+1][k-1]+dp[k][e]); 后面那个式子是因为我们这里不选择s这件衣服了,至于为什么要枚举到第k-1是因为,万一后面k~e区间中还存在c[k]==c[?],那么我们dp[k][e]就是要在这里面取最优的结果的,所以第一个区间是到k-1为止的。
推荐几个好懂的博客:http://www.cnblogs.com/neopenx/p/4050003.html http://www.cnblogs.com/kuangbin/archive/2013/04/29/3051392.html
http://www.cnblogs.com/ziyi--caolu/archive/2013/08/04/3236035.html
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define maxn 111 #define inf 99999999 int c[maxn]; int dp[maxn][maxn]; int main(){ int T,j=1; scanf("%d",&T); while(T--){ memset(dp,0,sizeof(dp)); int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&c[i]); dp[i][i]=1; } for(int s=n-1;s>=1;s--){ for(int e=s+1;e<=n;e++){ dp[s][e]=dp[s+1][e]+1; for(int k=s;k<=e;k++){ if(c[s]==c[k]) dp[s][e]=min(dp[s][e],dp[s+1][k-1]+dp[k][e]); } } } printf("Case %d: %d\n",j++,dp[1] ); } }
相关文章推荐
- iOS开发 - 获取当前网络状态
- Android 修改imei、gps等信息分析
- mysql学习(2)-MySQL服务器优化
- Wdate 触发input onchange事件的方法
- [leetcode] 19.Remove Nth Node From End of List
- 战斗
- 学习利用帮助文件的查看,并通过帮助命令学习基本命令
- 微信支付--返回异步数据封装
- 欧几里德算法及其扩展和中国剩余定理(暂时先写到这)
- 印象 ● sql函数
- php正则表达式
- 问题:MSChart.exe;结果:微软图表控件MsChart使用方法及各种插件下载地址
- 数据库(获取包含某字段的所有表名)
- BA-防冻开关的安装
- 自己动手写控件(模仿mvc htmlhelper的类)
- Hadoop学习笔记Day01
- 融云聚合会话报错的解决配置
- Android 动态类加载实现免安装更新
- 十六制颜色转换为RGB方法
- 一种基于流水线的视频文件校验方法