POJ1837 Balance(DP)
题意:
一个杠杆问题,给出一些悬挂位置,正数代表右边,负数代表左边,再给出一些不同重量的砝码,要求输出有几种平衡的可能
要点:
dp问题,主要是状态转移方程比较难写:dp[砝码i][力矩k+砝码i*挂钩j位置] += dp[砝码(i-1)][力矩k]
可以这么考虑,最后输出dp[i][maxn],因为每次砝码摆放位置不同,有很多种达到平衡的情况,那么每次都累加,最后就能算出有多少方案,这其实是dp的典型思想,多想想就会觉得很有道理。注意dp[0][maxn]=1,一开始如果都不放肯定平衡。
15292492 | Seasonal | 1837 | Accepted | 1636K | 16MS | C++ | 552B | 2016-03-20 14:45:29 |
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxn 7500 //通过加上一个较大的数来回避负数下标
int dp[25][15050];
int main()
{
int m, n,i,j,k;
int c[25], g[25];
scanf("%d%d", &m, &n);
for (i = 1; i <= m; i++)
scanf("%d", &c[i]);
for (i = 1; i <= n; i++)//注意因为后面有i-1,所以这里只能从1开始
scanf("%d", &g[i]);
memset(dp, 0, sizeof(dp));
dp[0][maxn] = 1; //一开始什么都不放是能达到平衡的
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
for (k = -7500; k <= 7500; k++)
if(dp[i-1][k+maxn]) //优化,只有当前i-1个砝码状态出现过,也就是这种力矩是可能的
dp[i][k + g[i] * c[j]+maxn] += dp[i - 1][k+maxn];//同一个dp因为每次加减的情况不同,一直累加数目
printf("%d\n", dp[n][maxn]);
return 0;
}