您的位置:首页 > 其它

挑战程序设计竞赛笔记_计数DP_P68

2017-08-19 18:48 465 查看
#include
const int MAX = 1000;
int n, m, M, a[MAX], dp[MAX + 1][MAX + 1];
void print(int row, int col)
{
printf("i/j |");
for (int i = 0; i <= col; i++)
printf("%4d", i);
printf("\n-----");
for (int i = 0; i <= col; i++)
printf("----");
for (int i = 0; i <= row; i++)
{
printf("\n%3d |", i);
for (int j = 0; j <= col; j++)
printf("%4d", dp[i][j]);
}
}
int main()
{
freopen("E:/My/input.txt", "r", stdin);
scanf("%d%d%d", &n, &m, &M);
printf("n = %d, m = %d, M = %d\n", n, m, M);
for (int i = 0; i < n; i++)
scanf("%d", a + i);
for (int i = 0; i <= n; i++)
dp[i][0] = 1;
for (int i = 0; i < n; i++)
for (int j = 1; j <= m; j++)
if (j > a[i])
dp[i + 1][j] = (dp[i + 1][j - 1] + dp[i][j] - dp[i][j - 1 - a[i]] + M) % M;
else
dp[i + 1][j] = (dp[i + 1][j - 1] + dp[i][j]) % M;
printf("result = %d\n", dp
[m]);
print(m, n);
return 0;
}


又是一下午,跪了...

if (a[i] >= j) $dp[i][j - k] = dp[i][j] + dp[i][j - 1] + ... + dp[i][0];

else           $dp[i][j - k] = dp[i][j] + dp[i][j - 1] + ... + dp[i][j - a[i] + 1] + dp[i][j - a[i]];

//else令j=j-1  $dp[i][j-1 - k] = dp[i][j-1] + dp[i][j-1 - 1] + ... + dp[i][j-1 - a[i] + 1] + dp[i][j-1 - a[i]];

整理           $dp[i][j - 1 - k] = dp[i][j - 1] + dp[i][j - 2] + ... + dp[i][j - a[i]] + dp[i][j - 1 - a[i]];

对比上面可以看出少了什么多了什么,所以有:

if (a[i] >= j) $dp[i][j - k] = $dp[i][j - 1 - k] + dp[i][j] - dp[i][j - 1 - a[i] < 0];

else $dp[i][j - k] = $dp[i][j - 1 - k] + dp[i][j] - dp[i][j - 1 - a[i] >= 0];

和上一篇同样,建议直接赋值i=1这行,从i=2开始循环。(或许这种题的套路就是这样?i=0这行的初始元素是1 0 0 ... 0就行?不懂,求解)

n = 3, m = 3, M = 10000

result = 6

 i/j |   0   1   2   3

---------------------

  0 |   1   0   0   0

  1 |   1   1   0   0

  2 |   1   2   2   1

  3 |   1   3   5   6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息