DP<背包?> POJ 1015
2012-07-18 14:38
393 查看
这道题我都不想写解题报告了..因为是看了一个很漂亮的acmer的解题报告写的~~
然后她写嘚很清楚吖~~~
真心佩服..
题意就是:
在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n 个人作为陪审团的候选人,然后再从这n 个人中选m 人组成陪审团。选m 人的办法是:控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0 到20。为了公平起见,法官选出陪审团的原则是:选出的m 个人,必须满足辩方总分D和控方总分P的差的绝对值|D-P|最小。如果有多种选择方案的 |D-P| 值相同,那么选辩控双方总分之和D+P最大的方案即可。
输出:
选取符合条件的最优m个候选人后,要求输出这m个人的辩方总值D和控方总值P,并升序输出他们的编号。
思路:
主要是用了两个数组:
dp[i][k].. 记录当选了 i 个人..辩控差是k的时候..辩控和最大值..
path[i][k].. 记录当选了 i 个人..辩控差是k..然后对应dp数组值<辩控和最大>的前一个人的编号..
注意因为是靠遍历所有点..然后找满足条件<dp[i-1][k] + pre[j].s > dp[i][k+pre[j].v]> 的 k 值..所以k值一定要是正数..所以就要弄一个修正值fix = 20*m..<因为当辩方值为0 控方值为 20的时候..和就是-20*m了..>
初始条件是当 i = 0 k就是0了.. 这时候dp[i][k] = 0
然后主要三层循环是:
第一层.. dp 中的 i 从0 - m..<确定m个人的 dp 数组值..>
第二层.. dp 中的 k 从0-fix*2..<看看有没有当 i 值确定情况下符合条件的 k 值.. 到 fix*2 的原因是fix 是等同于 0 >
<找满足条件的状态..>
第三层..遍历所有的點..查找满足条件的點..
当找到可以dp[i-1][k] + pre[j].s > dp[i][k+pre[j].v] 的點..并且没有加入审判团的~
就更改状态并更改相应路径..
感觉主要难确定的是每一维代表的变量..
Code:
那个漂亮的acmer写嘚很好吖~所以这里就不过多解释了..
贴上漂亮acmer的解题报告~我也要像她那么厉害~~~
優YoU /article/1968967.html
然后她写嘚很清楚吖~~~
真心佩服..
题意就是:
在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n 个人作为陪审团的候选人,然后再从这n 个人中选m 人组成陪审团。选m 人的办法是:控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0 到20。为了公平起见,法官选出陪审团的原则是:选出的m 个人,必须满足辩方总分D和控方总分P的差的绝对值|D-P|最小。如果有多种选择方案的 |D-P| 值相同,那么选辩控双方总分之和D+P最大的方案即可。
输出:
选取符合条件的最优m个候选人后,要求输出这m个人的辩方总值D和控方总值P,并升序输出他们的编号。
思路:
主要是用了两个数组:
dp[i][k].. 记录当选了 i 个人..辩控差是k的时候..辩控和最大值..
path[i][k].. 记录当选了 i 个人..辩控差是k..然后对应dp数组值<辩控和最大>的前一个人的编号..
注意因为是靠遍历所有点..然后找满足条件<dp[i-1][k] + pre[j].s > dp[i][k+pre[j].v]> 的 k 值..所以k值一定要是正数..所以就要弄一个修正值fix = 20*m..<因为当辩方值为0 控方值为 20的时候..和就是-20*m了..>
初始条件是当 i = 0 k就是0了.. 这时候dp[i][k] = 0
然后主要三层循环是:
第一层.. dp 中的 i 从0 - m..<确定m个人的 dp 数组值..>
第二层.. dp 中的 k 从0-fix*2..<看看有没有当 i 值确定情况下符合条件的 k 值.. 到 fix*2 的原因是fix 是等同于 0 >
<找满足条件的状态..>
第三层..遍历所有的點..查找满足条件的點..
当找到可以dp[i-1][k] + pre[j].s > dp[i][k+pre[j].v] 的點..并且没有加入审判团的~
就更改状态并更改相应路径..
感觉主要难确定的是每一维代表的变量..
Code:
#include <stdio.h> #include <algorithm> #include <cstring> using namespace std; struct Inf { int p; ///控方值 int d; ///辩方值 int s; ///控辩和 int v; ///控辩差 }pre[210]; int path[25][810];//记录所选定的候选人的编号 int dp[25][810];//dp[j][k]:取j个候选人,使其辩控差为k的所有方案中,辩控和最大的方案的辩控和 /*回溯,确认dp[j][k]方案是否曾选择过候选人i*/ bool select(int j, int k, int i) { while(j > 0 && path[j][k] != i) { k -= pre[path[j][k]].v; j--; } if(j == 0) return true; else return false; } int main() { int id[25]; int i, j, k; int n, m; int T = 0; while(scanf("%d %d", &n, &m) != EOF) { if(n == 0 && m == 0) break; memset(path, 0, sizeof(path)); memset(pre, 0, sizeof(pre)); memset(dp, -1, sizeof(dp));///一开始定义为-1..表示该方案不可行..以后状态转移找可行方案的时候用到.. for(i = 1; i <= n; ++i){ scanf("%d %d", &pre[i].p, &pre[i].d); pre[i].s = pre[i].p + pre[i].d; pre[i].v = pre[i].p - pre[i].d; } int fix = m*20;//总修正值,修正极限为从[-400,400]映射到[0,800] dp[0][fix] = 0; //由于修正了数值,因此dp[0][fix]才是真正的dp[0][0] /*DP*/ for(i = 1; i <= m; ++i) for(k = 0; k <= fix*2; ++k) if(dp[i-1][k] >= 0) for(j = 1; j <= n; ++j) if(dp[i-1][k] + pre[j].s > dp[i][k+pre[j].v] && select(i-1, k, j)){///!!!!Important~ select d+p is max while the solution is d-p dp[i][k+pre[j].v] = dp[i-1][k] + pre[j].s; path[i][k+pre[j].v] = j; } int k; for(k = 0; k <= fix; ++k){ if(dp[m][fix-k] >= 0 || dp[m][fix+k] >= 0) ///promise the d-p is min ///!!!!//从中间向两边搜索最小辨控差的位置k break; } int div = dp[m][fix-k] > dp[m][fix+k]?(fix-k):(fix+k);//最小辨控差 /*Output*/ int D = (dp[m][div] - div + fix)/2; //辩方总值 = (辨控和+辨控差-修正值)/2 int P = (dp[m][div] + div - fix)/2; //控方总值 = (辨控和-辨控差+修正值)/2 printf("Jury #%d\n", ++T); printf("Best jury has value %d for prosecution and value %d for defence:\n", P, D); for(i = 0, j = m, k = div; i < m; ++i){ id[i] = path[j][k]; k -= pre[id[i]].v; j--; } sort(id, id+m); for(i = 0; i < m; ++i) printf(" %d", id[i]); printf("\n\n"); } return 0; }
那个漂亮的acmer写嘚很好吖~所以这里就不过多解释了..
贴上漂亮acmer的解题报告~我也要像她那么厉害~~~
優YoU /article/1968967.html
相关文章推荐
- DP<01 背包> POJ 1837
- POJ1014:Dividing<动归,背包问题>
- poj 2506 Tiling <dp+大数加法>
- DP <裸> POJ 1157
- Android屏幕适配小技巧sw<n>dp
- POJ 2752(不满足P[i]<>P[next[i]] 的next函数)
- poj 2931 Building a Space Station <克鲁斯卡尔>
- 导弹拦截<DP><贪心><C++>
- DP<一维> 2058 龟兔赛跑
- hdu 2084 数塔 <dp(模板)>
- hdoj 2602<背包水>
- 树形DP <dfs+floyd> 【hlg】 1329 游乐园
- UVA 10534 - Wavio Sequence(自写set<node>优化o(n^2)dp)
- (POJ 1185)炮兵阵地 <状压DP经典题目>
- wata 哥 的 vector<MAX> G 第一次不能用 POJ 3321 树状数组
- poj 1014 Dividing <多重背包>
- islands打炉石传说<DP>
- poj 1423 Big Number<<求N!位数>>
- poj 1973 分配任务 进阶动态规划 <难题>
- 棋盘游戏&&binaryA+B<Dp,Dfs_with_Mem>