【发布时间】:2019-07-25 05:59:10
【问题描述】:
我了解解决方案的 DP 部分,但我不了解“回溯”部分,以及使用 i 设置位查找 j 长度数字的数量如何帮助解决问题?解决方案的粗体部分让我感到困惑。
问题:
Being a secret computer geek, Farmer John labels all of his cows with
binary numbers. However, he is a bit superstitious, and only labels cows
with binary numbers that have exactly K "1" bits (1 <= K <= 10). The
leading bit of each label is always a "1" bit, of course. FJ assigns
labels in increasing numeric order, starting from the smallest possible
valid label -- a K-bit number consisting of all "1" bits. Unfortunately,
he loses track of his labeling and needs your help: please determine the
Nth label he should assign (1 <= N <= 10^7).
INPUT FORMAT:
* Line 1: Two space-separated integers, N and K.
SAMPLE INPUT (file cowids.in):
7 3
INPUT DETAILS:
Among all binary numbers containing exactly 3 "1" bits, FJ wants to output
the 7th in increasing sorted order.
SAMPLE OUTPUT (file cowids.out):
10110
解决方案:
这个问题可以通过动态规划来解决。我们将 K=1 的输入视为一种特殊情况,因为这仅涉及打印一个 1 后跟 N-1 个零。对于 K 至少 2,快速粗略计算告诉我们答案中的总位数最多为 5000。对于二维数组 A[0..10][0.. 5000],我们让 A[i][j] 表示正好有 i 个 1 位的 j 位二进制数(包括以前导零开头的那些)的数量。我们可以通过设置 A[i][j] = A[i-1][j-1] + A[i][j-1] 来填写此表,因为具有 i 个 1 位的 j 位数字可以通过将 0 位附加到具有 i 个 1 位的 (j-1) 位数字,或通过将 1 位附加到具有 (i-1) 个 1 位的 (j-1) 位数字来获得。 填完表格后,从 A[K][5000] 开始的适当“回溯路径”会为我们提供我们要寻找的二进制数(注意不要打印前导零)。 "
解决方案代码:
#include <stdio.h>
#define M 5000
int A[11][M+1];
int leading_zeros = 1;
void print_sol(int n,int k,int m)
{
if (k==0 && m==1) return;
if (k==0 || A[k][m-1] >= n) {
if (!leading_zeros) printf ("0");
print_sol(n,k,m-1);
} else {
leading_zeros = 0;
printf ("1");
print_sol(n-A[k][m-1],k-1,m-1);
}
}
int main(void)
{
int i,j,N,K;
freopen ("cowids.in", "r", stdin);
freopen ("cowids.out", "w", stdout);
scanf ("%d %d", &N, &K);
if (K==1) {
printf ("1");
for (i=0; i<N-1; i++) printf ("0");
printf ("\n");
return 0;
}
A[0][1] = 1;
for (j=1; j<=M; j++) {
for (i=0; i<=10; i++) {
if (i==0) A[i][j] = 1;
else A[i][j] = A[i-1][j-1] + A[i][j-1];
if (A[i][j] > 10000000) A[i][j] = 10000000; /* avoid overflow */
}
}
print_sol(N,K,M);
printf ("\n");
return 0;
}
【问题讨论】:
-
“2012 USACO Cow Id (silver)”是编码比赛吗?
-
@halfer USA Computing Olympiad 是一项针对高中生的编程竞赛,用于为International Olympiad in Informatics 选择美国队的成员。
-
谢谢@Alexander,我让标题变得不那么麻烦了。
标签: algorithm dynamic-programming