这是我得到的平地机的作业之一。我已经在这个问题上苦苦挣扎了两天了。主题是关于动态编程,我不知道如何理解它。
详情如下。
条形码由不同排列的黑色和白色垂直线组成。为简单起见,我们使用字符串“0”和“1”来识别条形码,使得“0”表示黑线,而“1”表示白线。
条形码设计为对错误具有鲁棒性,因此必须遵循一些特定的规则:
1)条形码必须由 N 行
组成2)相同颜色的连续线不能超过 M 。例如,当 M = 3 时,条形码“01100001”是非法的,因为它包含四条连续的白线。但是,1001100是合法的。
3)我们如下定义“变色”。两个时发生颜色变化 连续的线条有不同的颜色。例如,1001100有3种颜色 改变。条形码必须具有完全 K 颜色变化。
4)第一行总是黑线。
我们有兴趣知道关于给定的可能条形码的数量 值 N , M 和 K 。
输入 只有一行包含3个整数N,M和K,其中1 <= N,M <= 30且0 <= K <= 30
输出 输出必须只包含一行,给出可能的条形码数量。
例如
输入
4 3 1
输出
3
输入
5 2 2
输出
3
输入
7 9 4
输出
15
答案 0 :(得分:1)
如果T(N,M,K)是输出,则有一个非常简单的递归关系:
T(N, M, K) = T(N - 1, M, K - 1) + T(N - 2, M, K - 1) + ... + T(N - M, M, K - 1)
有效条形码(N,M,K)始终是较小的有效条形码加上一种新颜色,此新颜色的大小可以是1到M之间的任何值。
由于这种关系,您可以为每个M创建一个N x K表,并使用动态编程解决O(N M K)中的问题。
这些规则应该足以初始化重复:
T(N, M, K) = 0 if (K >= N) and 1 if (K = N - 1)
T(N, M, K) = 0 if ((K+1) * M < N)
答案 1 :(得分:1)
在每个步骤(i条形码)我们有2个选项:选择白色还是黑色,然后根据更新你的状态(m和k)。
这里有一个带有评论的伪Java代码,不要犹豫,询问是否有不明确的内容:
static int n,m,k,memo[][][][];
static int dp(int i,int mm,int kk,int last) {
if(mm > m || kk > k) return 0; // limitation constrains
if(i==n) return kk==k?1:0; // if we build our barcode ( i == n ), we need to check color changing if it's ok return 1 else return 0
if(memo[i][mm][kk][last] != -1) return memo[i][mm][kk][last]; // momoization
int ans = 0;
ans += dp(i+1,last==1?mm+1:1,kk+(last!=1?1:0),1); // choose black as a color of this one and update state ( mm, kk )
ans += dp(i+1,last==0?mm+1:1,kk+(last!=0?1:0),0); // choose white as a color of this one and update state ( mm, kk )
return memo[i][mm][kk][last] = ans;
}
public static void main (String[] args) throws java.lang.Exception {
n = 4; m = 3; k = 1;
memo = new int[n+1][m+1][k+1][2];
for(int i=0;i<n;i++) for(int j=0;j<=m;j++) for(int l=0;l<=k;l++) Arrays.fill(memo[i][j][l], -1);
System.out.print(dp(1,1,0,1));
}