CodeForces 711C Coloring Trees(DP)
2016-09-22 16:12
375 查看
传送门:http://codeforces.com/problemset/problem/711/C
题目大意:
有若干个点,每个点开始有一个颜色值,如果有颜色,则用1~m表示涂有的颜色,如果没颜色用0表示。
定义美观度为,把点按序分组,相邻相同颜色的分为一组,有几组美观度就是几。
例如,颜色号分别为2, 1, 1, 1, 3, 2, 2, 3, 1, 3.则美观度为7,因为分组情况为: {2}, {1, 1, 1}, {3}, {2, 2}, {3}, {1}, {3}.
已知给第i个点涂第j种颜色需要的油漆数为p[i][j]。
输入美观度b,问要想使得美观度为b,至少需要多少油漆?
题目分析:
“至少”、“最优”的问题通常往动态规划去考虑。而且这里的分组情况也只需从左往右看,并且当前节点i的美观度受前I-1个点的美观度和第i-1个点的颜色有关系(如果相同则美观度不变,不同则加1)。
基于以上分析,开dp数组如下:
dp[i][j][k]表示涂到第i个节点,前i-1个节点的美观度为j,第i-1个点的颜色为k这三个条件下的最小油漆数。
先初始化为无穷大,然后逐步往小了转移就可以了。转移方程有点复杂,用LaTeX写太累了,具体看代码吧,还是很清晰的。
复杂度:O(n∗m2∗b),因为题中n,m,b的数量级均为10^2,所以肯定可以通过。
官方题解中好像有O(n∗m∗b)的解法,看不懂ing
题目大意:
有若干个点,每个点开始有一个颜色值,如果有颜色,则用1~m表示涂有的颜色,如果没颜色用0表示。
定义美观度为,把点按序分组,相邻相同颜色的分为一组,有几组美观度就是几。
例如,颜色号分别为2, 1, 1, 1, 3, 2, 2, 3, 1, 3.则美观度为7,因为分组情况为: {2}, {1, 1, 1}, {3}, {2, 2}, {3}, {1}, {3}.
已知给第i个点涂第j种颜色需要的油漆数为p[i][j]。
输入美观度b,问要想使得美观度为b,至少需要多少油漆?
题目分析:
“至少”、“最优”的问题通常往动态规划去考虑。而且这里的分组情况也只需从左往右看,并且当前节点i的美观度受前I-1个点的美观度和第i-1个点的颜色有关系(如果相同则美观度不变,不同则加1)。
基于以上分析,开dp数组如下:
dp[i][j][k]表示涂到第i个节点,前i-1个节点的美观度为j,第i-1个点的颜色为k这三个条件下的最小油漆数。
先初始化为无穷大,然后逐步往小了转移就可以了。转移方程有点复杂,用LaTeX写太累了,具体看代码吧,还是很清晰的。
复杂度:O(n∗m2∗b),因为题中n,m,b的数量级均为10^2,所以肯定可以通过。
官方题解中好像有O(n∗m∗b)的解法,看不懂ing
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define INF 0x3f3f3f3f #define INF64 0x3f3f3f3f3f3f3f3f ll dp[105][105][105]; int c[105]; int p[105][105]; int main() { memset(dp,0x3f,sizeof(dp)); int n,m,b; scanf("%d %d %d",&n,&m,&b); for(int i=1;i<=n;i++) { scanf("%d",&c[i]); } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&p[i][j]); } } if(c[1]==0) {//第1棵树没涂颜色,则美观度为1,代价为p[1][i] for(int i=1;i<=m;i++) dp[1][1][i]=p[1][i]; } else //涂了颜色i,那就只需初始化第i棵树的颜色 dp[1][1][c[1]]=0; for(int i=2;i<=n;i++) { for(int j=1;j<=b;j++) { for(int k=1;k<=m;k++) { if(c[i]!=0) { if(c[i]==k) { dp[i][j][k]=dp[i-1][j][k]; for(int s=1;s<=m;s++) if(s!=k) dp[i][j][k]=min(dp[i][j][k],dp[i-1][j-1][s]); } else dp[i][j][k]=INF64; } else { ll temp=dp[i-1][j][k]; for(int s=1;s<=m;s++) if(s!=k) temp=min(temp,dp[i-1][j-1][s]); dp[i][j][k]=temp+p[i][k]; } } } } ll ans=INF64; for(int i=1;i<=m;i++) ans=min(ans,dp [b][i]); if(ans>=INF64) printf("-1\n"); else printf("%I64d\n", ans); }
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- 简单谈谈Android中SP与DP的区别
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- 关于UI切图与开发 px和dp
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告