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;
}


posted @ 2016-03-20 15:17  seasonal  阅读(72)  评论(0编辑  收藏  举报