首页 > 学院 > 开发设计 > 正文

POJ - 1837 Balance解题报告

2019-11-06 08:13:11
字体:
来源:转载
供稿:网友
题目大意:给你一个天平m(20)个挂钩,挂钩到中心的举例为[1,15],和n个重物(20)重量范围[1-25],要求所有重物都要挂在挂钩上,问你有多少种挂法可以让天平平衡。思路:n个重物,每个重物都有可能挂到m个挂钩的任意一个上,枚举m^n种情况。好吧,心急了,没好好想,就去看了题解,感觉dp看了题解再打代码就像抄答案,别人一句描述状态的话读完就神秘感全无。dp建立:

a[i][j]表示把前i个重物都挂上之后,平衡度为j的情况数。g[i]表示第i个物体的重量。d[i]表示第i个挂钩到中心的距离(正负表示左右)。

注意由于这里平衡度有可能出现负数的情况,所有都加上相同的常数,即平移j范围集合[-20*25*15,20*25*15]向右平移7500。 

递推方法:对于第i个重物,枚举它挂在每个挂钩上的情况(枚举j),a[i][k]+=a[i-1][k-g[i]*d[j]];

边界条件:a[1][g[1]*d[i]]=1;

#include<iostream>#include<math.h>#include<stdio.h>#define P 7500using namespace std;int m,n;int d[30]={0};int g[30]={0};int a[30][2*P+50]={0};int main(){	cin>>m>>n;	for(int i=1;i<=m;i++)	{		scanf("%d",&d[i]);	}	for(int i=1;i<=n;i++)	{		scanf("%d",&g[i]);	}	for(int i=1;i<=m;i++)//确定边界条件 	{		a[1][d[i]*g[1]+P]=1;	}	for(int i=2;i<=n;i++)	{		for(int j=1;j<=m;j++)		{			for(int k=0;k<=2*P;k++)			{				if(k-d[i]*g[j]<0)continue;				a[i][k]+=a[i-1][k-d[j]*g[i]];			}		}	}	cout<<a[n][P];}相比暴力枚举,动态规划少算了的就是,前i-1个重物都挂上之后,i个重物挂在不同的位置,需要再重新枚举前i-1个挂法的重复部分。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表