您的位置:首页 > 其它

POJ 1426 Find The Multiple(DP + 抽象01背包)

2013-03-19 19:38 381 查看
题意:

给定一个数 n(n <= 200), 输出一个由 01 组成的十进制数(长度不超过100),并且这个数是 n 的倍数。

思路:

1. 由于题目限定了 n 的范围以及输出的范围,普通的 DFS/BFS 是能够解题的,只不过时间复杂度较高,达到 70ms+;

2. 抓住由“01 组成的十进制数”这个特性,可以把问题抽象成由:1,10,100,1000,10000……其中任意多个组成的符合题意的数;

3. dp[i][j] 表示前 i 个数,能否表示成余 j 的形式,能则记录最小的一个;不能则为 0。dp[i][j] = min(dp[i-1][j], dp[i-1][r] + 10i);

4. 特别注意的是,当 j = 0 时,要特殊处理下,因为即使 dp[i-1][0] = 0, 去求 dp[i][r] 仍然是正确且必要的。最终时间为 0ms;

#include <iostream>
#include <algorithm>
using namespace std;

__int64 dp[110][210];

__int64 solve(int n) {
int rem = 1;
__int64 exp = 1;

memset(dp[0], 0, sizeof(dp[1]));
dp[0][1] = 1;

for (int i = 1; i <= 100; i++) {
exp *= 10;
rem = (rem * 10) % n;
for (int j = 0; j < n; j++) {
dp[i][j] = dp[i-1][j];
}
for (int j = 0; j < n; j++) {
if (dp[i-1][j] || j == 0) {
int r0 = (j + rem) % n;
if (dp[i][r0] == 0)
dp[i][r0] = exp + dp[i-1][j];
if (r0 == 0)
return dp[i][r0];
}
}
}
return 0;
}

int main() {
int n;
while (scanf("%d", &n) && n) {
if (n == 1)
printf("1\n");
else
printf("%I64d\n", solve(n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: