三维dp&codeforce 369_2_C

标签: dp


codeforce 369_2_C

题意: 一排树,初始的时候有的有颜色,有的没有颜色,现在给没有颜色的树染色,给出n课树,用m种燃料涂,将相邻相同颜色的树划为一组,最后使得组数为k,并且所用燃料的量最小,给出了每棵树涂j种燃料的用量,如果存在这种涂法输出最小用量,不存在输出-1;

题解: 很容易看出是一个三维dp, dp[i][j][k] 表示处理到第i棵树,最后一棵树为颜色j,现在已经分成的组数为k的时候的最小用量

转移方程如果当前树初始有颜色,那么不能再涂其他颜色,则dp[i][j][k] = min(dp[i-1][j][k],dp[i-1][非j][k-1]);

如果现在树可以涂颜色那么有dp[i][j][k] = min(dp[i-1][j][k] + cost[j],dp[i-1][j][k-1] + cost[j]);

三维dp或者是普通dp要仔细想清楚的都是初始化,还是建议画图,直观的看,在当前的值计算前要先计算出哪些值,这样才可以知道转移的顺序和初始化的值,对于这个题,每次都是从上一次来的,所以对第一层的初始化就很有必要了,可以参考代码看具体如何初始化的,然后要注意是找最小值,所以一开始将所有状态初始化成INF

官方题解:

(它和我定义的有一点点区别,第二维和第三维反了,但是本质不影响)We compute the following array : dp[i][j][k] denoting the minimum amount of paint needed to color the first i trees such that it has beauty j and the i-th tree is colored by color k, and initialize all these values to ∞. We can compute this dp array easily by considering two cases :

1,When the last color used is equal to the current color, then we should compare it with dp[i - 1][j][k] + cost[i][k] if it was originally uncolored or dp[i - 1][j][k] otherwise, since the beauty of the coloring is the same.

2,When the last color used is different from the current color, then we should compare it with dp[i - 1][j - 1][l] + cost[i][k] or dp[i - 1][j - 1][l] for all 1 ≤ l ≤ m except when l is equal to the current color, by similar reasoning.

If the current tree is uncolored, we loop through all the m possible colors to color it.

Naively implementing this dp will give an O(nkm2), which is sufficient to pass for this problem. However, it is possible to optimize it into O(nkm) by avoiding iterating through all colors when considering the last color used and store two global minimums. See the code for more the details.

Time Complexity : O(nkm2) or O(nkm)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<algorithm>
using namespace std;
#define ll long long
const ll INF = (ll)1e18;
const int N = 108;
ll dp[N][N][N];
int init[N];
ll cost[N][N];
int main()
{
int n,m,c;
while(~scanf("%d%d%d",&n,&m,&c))
{
for(int i = 1; i <= n; i++)
{
scanf("%d",&init[i]);
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
scanf("%I64d",&cost[i][j]);
}
}
for(int i = 0; i <= n; i++)
for(int j = 0; j <= m; j++)
for(int k = 0; k <= c; k++)
dp[i][j][k] = INF;
if(init[1]==0)
{
for(int i = 1; i <= m; i++)
{
dp[1][i][1] = cost[1][i];
}
}
else dp[1][init[1]][1] = 0;
for(int i = 2; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
for(int k = 1; k <= c; k++)
{
if(init[i]!=0)
{
if(j!=init[i]) {
dp[i][j][k] = INF;
continue;
}
else {
for(int u = 1; u <= m; u++)
{
if(u==j) dp[i][j][k] = min(dp[i-1][u][k],dp[i][u][k]);
else if(u!=j) {
dp[i][j][k] = min(dp[i][j][k],dp[i-1][u][k-1]);
}
}
}
}
else if(init[i]==0)
{
for(int u = 1; u <= m; u++)
{
if(u==j){
dp[i][j][k] = min(dp[i-1][j][k] + cost[i][j],dp[i][j][k]);
}
else if(u!=j)
{
dp[i][j][k] = min(dp[i-1][u][k-1] + cost[i][j],dp[i][j][k]);
}
}
}
}
}
}
ll ans = INF;
for(int i = 1; i <= m; i++)
{
ans = min(dp[n][i][c],ans);
}
if(ans==INF)
puts("-1");
else printf("%I64d\n",ans);
}
return 0;
}

三维dp&codeforce 369_2_C的更多相关文章

  1. P1006 传纸条(二维、三维dp)

    P1006 传纸条 输入输出样例 输入 #1 复制 3 3 0 3 9 2 8 5 5 7 0 输出 #1 复制 34 说明/提示 [限制] 对于 30% 的数据,1≤m,n≤10: 对于 100% ...

  2. HDU 5965 三维dp 或 递推

    题意:= =中文题 思路一:比赛时队友想的...然后我赛后想了一下想了个2维dp,但是在转移的时候,貌似出了点小问题...吧?然后就按照队友的思路又写了一遍. 定义dp[i][j][k],表示第i列, ...

  3. 三维dp

    https://cn.vjudge.net/contest/245857#problem/C 代码: #include<iostream> #include<string> # ...

  4. UVA 12063 Zeros and Ones(三维dp)

    题意:给你n.k,问你有多少个n为二进制的数(无前导零)的0与1一样多,且是k的倍数 题解:对于每个k都计算一次dp,dp[i][j][kk][l]表示i位有j个1模k等于kk且第一位为l(0/1) ...

  5. UVALive - 2031 Dance Dance Revolution 三维dp

    题目大意:有一个胖子在玩跳舞机.刚開始的位置在(0,0).跳舞机有四个方向键,上左下右分别相应1,2,3,4.如今有下面规则 1.假设从0位置移动到随意四个位置,消耗能量2 2.假设从非0位置跳到相邻 ...

  6. hdu 4826 三维dp

    dp的问题除了递推过程的设计之外 还有数据结构的选择以及怎样合理的填充数据 这个的填充是个坑..#include<iostream> #include<cstdio> #inc ...

  7. codevs1169传纸条 不相交路径取最大,四维转三维DP

    这个题一个耿直的思路肯定是先模拟.. 但是我们马上发现这是具有后效性的..也就是一个从(1,1)开始走,一个从(n,m)开始走的话 这样在相同的时间点我们就没法判断两个路径是否是相交的 于是在dp写挂 ...

  8. Caesar's Legions(三维dp)

    Caesar's Legions Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u S ...

  9. poj 1037 三维dp

    A decorative fence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7221   Accepted: 272 ...

随机推荐

  1. C 标准I/O库粗略实现

    本文同时发表在 https://github.com/zhangyachen/zhangyachen.github.io/issues/123 写一下fopen/getc/putc等C库的粗略实现,参 ...

  2. python各种类型的转换

    #进制转换 ord(x) #将一个字符转换为它的整数值 hex(x) #将一个整数转换为一个十六进制字符串 oct(x) #将一个整数转换为一个八进制字符串 #类型转换int(x [,base ]) ...

  3. C#又能出来装个B了。一步一步微信跳一跳自动外挂

    PS:语言只是载体.思维逻辑才是王道 前天看见了个python的脚本.于是装python.配置环境变量.装pip.折腾了一上午,最终装逼失败. 于是进入博客园,顶部有篇文章吸引了我 .NET开发一个微 ...

  4. bzoj 1150: [CTSC2007]数据备份Backup

    Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家 ...

  5. python科学计算_numpy_函数库

    1.常规函数与排序 常用统计函数: 求和:sum().均值:mean().标准差:std().方差:var().最小值:min().最大值:max().最大值与最小值之差:ptp().最大值的下标:a ...

  6. Optimize For Ad Hoc Workloads

    --临时工作负载优化   即席查询:也就是查询完没放到Cache当中,每次查询都要重新经过编译,并发高的时候很耗性能: 参数化查询: 一方面解决了重编译问题,但随着数据库数据数据的变更,统计信息的更新 ...

  7. [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解

    接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...

  8. Spring异常处理@ExceptionHandler

    最近学习Spring时,认识到Spring异常处理的强大.之前处理工程异常,代码中最常见的就是try-catch-finally,有时一个try,多个catch,覆盖了核心业务逻辑: try{ ... ...

  9. CSS中的url()到底要不要加引号

    如:url(images/background.gif)和 url("images/background.gif") 从安全角度来讲是要加上的 否则容易被xss 因为"& ...

  10. springboot mybatis 事务管理

    本文主要讲述springboot提供的声明式的事务管理机制. 一.一些概念 声明式的事务管理是基于AOP的,在springboot中可以通过@Transactional注解的方式获得支持,这种方式的优 ...