三维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. ArcGIS API for JavaScript 4.2学习笔记[24] 【IdentifyTask类】的使用(结合IdentifyParameters类)(第七章完结)

    好吧,我都要吐了. 接连三个例子都是类似的套路,使用某个查询参数类的实例,结合对应的Task类,对返回值进行取值.显示. 这个例子是Identify识别,使用了TileLayer这种图层,数据来自Se ...

  2. solr安装配置

    1.solr是基于tomcat安装部署的 2.网上下载solr-5.2.1 http://lucene.apache.org/solr/downloads.html 3.解压solr文件 tar zx ...

  3. 9.nginx使用redis用缓存

    需要使用到的第三方模块,因为在有道笔记上面,所以为办法直接给你们,需要的话给我私信或者邮件(913956964@qq.com) 1.编译安装,添加上述扩展插件 ./configure --prefix ...

  4. vue过滤数字为2位小数点,过滤器

    过滤数字为2位小数点 filters: { //保留2位小数点过滤器 不四舍五入 number(value) { var toFixedNum = Number(value).toFixed(3); ...

  5. python自动安装mysql5.7

    python自动安装mysql5.7 python版本:python2.6 centos版本:centos6.9 mysql版本:mysql5.7.19 安装目录路径和数据目录路径都是固定,当然也可以 ...

  6. Python sort方法

    官方文档: sort(*, key=None, reverse=False) This method sorts the list in place, using only < comparis ...

  7. vmware workstation14永久激活密钥分享

    vmware workstation14永久激活密钥分享 VMware Workstation是一款功能强大的桌面虚拟计算机软件,简单来说就是最强的中文虚拟机了,可以在桌面上运行不同的操作系统,下面就 ...

  8. linux 操作中命令备忘

    1 使用grep 查询关键内容 如果你想在当前目录下 查找"hello,world!"字符串,可以这样: grep -rn "hello,world!" * * ...

  9. python实现二分查找算法

    二分查找算法也成为折半算法,对数搜索算法,一会中在有序数组中查找特定一个元素的搜索算法.搜索过程是从数组中间元素开始的 如果中间元素正好是要查找的元素,则搜索过程结束:如果查找的数大于中间数,则在数组 ...

  10. linux系统中,文件的三种特殊权限

    背景介绍 在linux系统中,我们熟知有rwx三种权限,对应所有者,同组用户,其他用户三种用户的权限,一共9个位来指定一个文件的权限情况,通过chmod xxx 来更改权限属性,其中xxx是已八进制表 ...