ZOJ_Tug of War DP
来源:互联网 发布:php base64解码函数 编辑:程序博客网 时间:2024/05/22 06:59
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1880
题意:给定n个数,要求分成两组,每组的个数最多相差1,求两组数的和相差最小的情况。
算法: 经典DP。
分析:用dp[i][j] 表示i个人的体重之和为j是否可能,显然转移应该从dp[i-1][j-?]来转移,但是
这里有一个问题,就是最后选进来的那个人如果设为k的话,因为没有规定i个人的范围,因此
这里的状态表示就没有“无后效性”了。 这里可以这么看,我们可以增加一个状态k,用dp[k][i][j]
表示前k个人中选取i个人,体重之和为j是否可能。则得到转移方程为:
dp[k][i][j] = dp[k-1][i][j] || dp[k-1][i-1][j-w[k]],即考虑第k个人取或者不取。
其实这个状态的得出也可以通过另外一个方面来得到,即:dp[i][j] 的求解的时候,k的for循环
放在最外层,这样就可以保证每个数只被考虑一次。
代码:
#include<stdio.h>#include<string.h>#include<stdlib.h>#define min(a,b) (a>b?b:a)#define max(a,b) (a>b?a:b)int n,sum;int w[101];int dp[101][45001];void DP(){memset(dp,0,sizeof(dp));dp[0][0] = 1;for(int k=1;k<=n;k++){for(int i=k;i>=1;i--){for(int j=0;j<=sum;j++){if(dp[i-1][j] == 1){dp[i][j+w[k]] = 1;dp[i][j] = 1 ;}}}}int ave = n/2,res=0x7fffffff,min_,max_;for(int j=0;j<=sum;j++){if(dp[ave][j]==1 && dp[n-ave][sum-j]==1){if(res > abs(sum-2*j)){res = abs(sum-2*j) ;min_ = min(j,sum-j);max_ = max(j,sum-j);}}}printf("%d %d\n",min_,max_);}int main(){while(scanf("%d",&n)!=EOF){sum = 0 ;for(int i=1;i<=n;i++){scanf("%d",&w[i]);sum += w[i] ;}DP();}return 0;}
- ZOJ_Tug of War DP
- ZOJ1880 POJ2576 Tug of War,DP
- hdu 2809 God of War //状态压缩DP
- HDU - 2809 God of War (DP+状态压缩)
- Light oj 1147 - Tug of War(状压dp)
- lightoj 1147 - Tug of War DP压位
- POJ 2576 / Light OJ 1147 Tug of War 状态压缩DP
- Tug of War
- Tug of War
- poj2576 tug of war
- Tug of War
- ZCMU-Tug of War
- War of the Worlds
- 【DP】 POJ 1085 Triangle War
- A War of Scheme Selection
- nbu 2430 war of energy
- ZOJ 1880 Tug of War
- hdu 2809 God of War
- 浅析C++中内存分配的方式
- 论坛中版主给帖子设置高亮显
- Suse中设置用SSH远程连接
- C++中的临时对象
- android笔记
- ZOJ_Tug of War DP
- c++中的#include "stdafx.h"(转自新浪博客)
- VB 及 Lotusscript中 Resume 的用法
- 怎样清理没有用到的图片
- 辗转相除法
- Redis提供了丰富的命令
- 数据库索引类型
- #pragma once
- TDriver on Windows 安装笔记