poj 2184 dp(兼具聪明和幽默的奶牛)
2014-11-04 20:09
267 查看
题意:有n头奶牛,每个奶牛有一个聪明值(s)和幽默值(f)(-1000<=值<=1000)。现欲选出若干奶牛,使得这些奶牛的聪明值之和与幽默值之和再求和所得的数值最大,且需要满足聪明值之和和幽默值之和都非负。
思路:一开始以为和1015陪审团是同样的思路,后来发现不行。于是参考了http://www.cnblogs.com/rainydays/archive/2012/07/04/2576077.html
思路变为d[i][s]=f的形式。表示用前i头牛构成s属性和为s的情况下f属性和最大为多少。状态转移从两种情况来,即用或者不用当前的牛。dp[i][j] = max(dp[i - 1][j - s[i]] + f[i], dp[i - 1][j])。在实际操作的时候可以将第一维去掉,进行空间上的优化。但是由于s[i]的值有正有负,所以在填写数组的顺序要根据s[i]的值来决定,若为正则从右到左(类似01背包的空间优化),若为负则从左到右。
注意:动态规划中状态维和值是可以相互转化的。状态维过多,效率低的时候,可以把将其转化为数组值;同理,数组值不唯一无法规划时,可以增加状态维使状态更详细。
循环边界可以直接从0到2M,见版本1。
我写的两个循环边界是:for(j = M+i*1000-1000;j>=0;j--)和for(j = M-i*1000+1000;j<=M*2;j++)。又参考了http://blog.csdn.net/qinmusiyan/article/details/8028627的思路后缩小了边界范围。见版本2。
版本1:
版本2:
思路:一开始以为和1015陪审团是同样的思路,后来发现不行。于是参考了http://www.cnblogs.com/rainydays/archive/2012/07/04/2576077.html
思路变为d[i][s]=f的形式。表示用前i头牛构成s属性和为s的情况下f属性和最大为多少。状态转移从两种情况来,即用或者不用当前的牛。dp[i][j] = max(dp[i - 1][j - s[i]] + f[i], dp[i - 1][j])。在实际操作的时候可以将第一维去掉,进行空间上的优化。但是由于s[i]的值有正有负,所以在填写数组的顺序要根据s[i]的值来决定,若为正则从右到左(类似01背包的空间优化),若为负则从左到右。
注意:动态规划中状态维和值是可以相互转化的。状态维过多,效率低的时候,可以把将其转化为数组值;同理,数组值不唯一无法规划时,可以增加状态维使状态更详细。
循环边界可以直接从0到2M,见版本1。
我写的两个循环边界是:for(j = M+i*1000-1000;j>=0;j--)和for(j = M-i*1000+1000;j<=M*2;j++)。又参考了http://blog.csdn.net/qinmusiyan/article/details/8028627的思路后缩小了边界范围。见版本2。
版本1:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <cstdlib> using namespace std; #define clc(s,t) memset(s,t,sizeof(s)) #define INF 0x3fffffff #define N 100000 int a[105],b[105]; int dp[(N<<1)+5]; int n; int main(){ int i,j,res=0; scanf("%d",&n); for(i = 1;i<=n;i++) scanf("%d %d",&a[i],&b[i]); for(i = 0;i<=2*N;i++) dp[i] = -INF; dp = 0; for(i = 1;i<=n;i++){ if(a[i] >= 0){ for(j = 2*N-a[i];j>=0;j--) if(dp[j] != -INF) dp[j+a[i]] = max(dp[j+a[i]],dp[j]+b[i]); }else{ for(j = -a[i];j<=2*N;j++) if(dp[j] != -INF) dp[j+a[i]] = max(dp[j+a[i]],dp[j]+b[i]); } } for(i = N;i<=2*N;i++) if(dp[i]>=0) res = max(res,i+dp[i]-N); printf("%d\n",res); return 0; }
版本2:
#include <stdio.h> #include <string.h> #define max(a,b) ((a)>(b)?(a):(b)) #define INF 0x3fffffff #define N 105 #define M 100000 int n,m; int dp[M*2+5],s ,f ; int main(){ //freopen("a.txt","r",stdin); while(scanf("%d",&n)!=EOF){ int i,j,res=0,high,low; high = low = M; for(i = 1;i<=n;i++) scanf("%d %d",&s[i],&f[i]); for(i = 0;i<=M*2;i++) dp[i] = -INF; dp[M] = 0; for(i = 1;i<=n;i++){ if(s[i] >= 0){ for(j = high;j>=low;j--) dp[j+s[i]] = max(dp[j+s[i]],dp[j]+f[i]); high += s[i]; } else{ for(j = low;j<=high;j++) dp[j+s[i]] = max(dp[j+s[i]],dp[j]+f[i]); low += s[i]; } } for(i = M;i<=M*2;i++) if(dp[i]>=0) res = max(res,i-M+dp[i]); printf("%d\n",res); } return 0; }
相关文章推荐
- poj 3616 奶牛产奶时间间隔dp
- POJ 2184 Cow Exhibition 奶牛展(01背包,变形)
- poj 2184 DP
- POJ 2184 Cow Exhibition (dp)
- poj 2184 Cow Exhibition dp
- POJ 2184 Cow Exhibition(DP:01背包)
- POJ 2184 Cow Exhibition [dp 背包]
- poj 3616 区间dp(奶牛产奶)
- poj_2184_dp
- [POJ 2184]Cow Exhibition[DP][01背包]
- Cow Exhibition POJ - 2184 特殊的01背包,有助于理解dp循环方向
- Poj 2184 (dp)
- POJ 2184 DP
- POJ 2184 DP
- poj 2184 Cow Exhibition(dp之01背包变形)
- DP:Cow Exhibition(POJ 2184)(二维问题转01背包)
- POJ 2184 Cow Exhibition(DP)
- poj 2184(dp变形,进一步加深01背包)
- poj 2184(dp变形,进一步加深01背包)
- POJ-2184 Cow Exhibition(01背包变形)