POJ 1015 陪审团人选 [动态规划]
2010-08-19 21:22
375 查看
动态规划太深奥了,太难规了,这题又是看《程序设计引导及在线实践》上面的思路和代码做的,具体规划思路如下:
用f[i][j]表示,取i个候选人,使其辩控差为j 的所有方案中,辩控和最大的那个方案的控辩和。
要求f[i][j] 显然要从一个可行的方案 f[i-1][x] 演化而来。可行方案f(i-1, x)能演化成方案f(j, k)的必要条件是:
存在某个候选人k,k 在方案f(i-1, x)中没有被选上,且x+V(k) = j;(V(k)为第k个人的控辩差);
选出 f(i-1, x) + S(k)(控辩和) 的值最大的那个,那么方案f(i-1, x)再加上候选人k,就演变成了方案 f(i, j)。
这中间需要将一个方案都选了哪些人都记录下来。不妨将方案f(i, j)中最后选的那个候选人的编号,记在二维
数组的元素path[i][j]中。那么方案f(i, j)的倒数第二个人选的编号,就是path[i-1][j-V[path[i][j]]。
假定最后算出了解方案的辩控差是k,那么从path[m][k]出发,就能顺藤摸瓜一步步求出所有被选中的候选人。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int compare(void const* a, void const* b)
{
return *(int*)a - *(int*)b;
}
int main()
{
int n, m, i, j, k, t1, t2, casenum=1, min;
int f[21][1000], p[201], d[201], path[21][1000];
int Qnum[21], Q[21][900]; //队列
int ans[21];
while (scanf("%d %d", &n, &m) && n)
{
memset(f, -1, sizeof(f)); //这样也行!!赋值之后是-1;为什么呢???
memset(Qnum, 0, sizeof(Qnum));
for (i=1; i<=n; i++)
{
scanf("%d %d", &p[i], &d[i]);
}
Q[0][0] = 400;
Qnum[0] = 1;
f[0][400] = 0;
for (i=0; i<m; i++)
{
for (j=0; j<Qnum[i]; j++)
{
for (k=1; k<=n; k++)
{
if(f[i][Q[i][j]]+p[k]+d[k] > f[i+1][Q[i][j]+p[k]-d[k]])
{
t1 = i; //以下检验k是否已经在f[i][Q[i][j]]中被选上
t2 = Q[i][j];
while (t1>0 && path[t1][t2]!=k)
{
t2 -= p[path[t1][t2]]-d[path[t1][t2]];
t1--;
}
if (t1==0) //没有被选上,可选
{
if (f[i+1][Q[i][j]+p[k]-d[k]] == -1)
{ //添加到队列
Q[i+1][Qnum[i+1]] = Q[i][j]+p[k]-d[k];
Qnum[i+1]++;
}
f[i+1][Q[i][j]+p[k]-d[k]] = f[i][Q[i][j]]+p[k]+d[k];
path[i+1][Q[i][j]+p[k]-d[k]] = k;
}
}
}
}
}
min = 900; //计算控方和辩方差值的绝对值最小值
for (i=0; i<Qnum[m]; i++)
{
if (abs(Q[m][i]-400) < min) min = abs(Q[m][i]-400);
}
if (f[m][400+min] > f[m][400-min]) min = min+400; //选最小差值中总分和最大的
else min = 400-min;
printf("Jury #%d\n", casenum++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",
(min-400+f[m][min])/2, (400-min+f[m][min])/2);
for (i=0; i<m; i++) //从后往前依次找被选中的m个人
{
ans[i] = path[m-i][min];
min -= p[ans[i]]-d[ans[i]];
}
qsort(ans, m, sizeof(int), compare);
for (i=0; i<m; i++)
printf(" %d", ans[i]);
printf("\n\n");
}
}
用f[i][j]表示,取i个候选人,使其辩控差为j 的所有方案中,辩控和最大的那个方案的控辩和。
要求f[i][j] 显然要从一个可行的方案 f[i-1][x] 演化而来。可行方案f(i-1, x)能演化成方案f(j, k)的必要条件是:
存在某个候选人k,k 在方案f(i-1, x)中没有被选上,且x+V(k) = j;(V(k)为第k个人的控辩差);
选出 f(i-1, x) + S(k)(控辩和) 的值最大的那个,那么方案f(i-1, x)再加上候选人k,就演变成了方案 f(i, j)。
这中间需要将一个方案都选了哪些人都记录下来。不妨将方案f(i, j)中最后选的那个候选人的编号,记在二维
数组的元素path[i][j]中。那么方案f(i, j)的倒数第二个人选的编号,就是path[i-1][j-V[path[i][j]]。
假定最后算出了解方案的辩控差是k,那么从path[m][k]出发,就能顺藤摸瓜一步步求出所有被选中的候选人。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int compare(void const* a, void const* b)
{
return *(int*)a - *(int*)b;
}
int main()
{
int n, m, i, j, k, t1, t2, casenum=1, min;
int f[21][1000], p[201], d[201], path[21][1000];
int Qnum[21], Q[21][900]; //队列
int ans[21];
while (scanf("%d %d", &n, &m) && n)
{
memset(f, -1, sizeof(f)); //这样也行!!赋值之后是-1;为什么呢???
memset(Qnum, 0, sizeof(Qnum));
for (i=1; i<=n; i++)
{
scanf("%d %d", &p[i], &d[i]);
}
Q[0][0] = 400;
Qnum[0] = 1;
f[0][400] = 0;
for (i=0; i<m; i++)
{
for (j=0; j<Qnum[i]; j++)
{
for (k=1; k<=n; k++)
{
if(f[i][Q[i][j]]+p[k]+d[k] > f[i+1][Q[i][j]+p[k]-d[k]])
{
t1 = i; //以下检验k是否已经在f[i][Q[i][j]]中被选上
t2 = Q[i][j];
while (t1>0 && path[t1][t2]!=k)
{
t2 -= p[path[t1][t2]]-d[path[t1][t2]];
t1--;
}
if (t1==0) //没有被选上,可选
{
if (f[i+1][Q[i][j]+p[k]-d[k]] == -1)
{ //添加到队列
Q[i+1][Qnum[i+1]] = Q[i][j]+p[k]-d[k];
Qnum[i+1]++;
}
f[i+1][Q[i][j]+p[k]-d[k]] = f[i][Q[i][j]]+p[k]+d[k];
path[i+1][Q[i][j]+p[k]-d[k]] = k;
}
}
}
}
}
min = 900; //计算控方和辩方差值的绝对值最小值
for (i=0; i<Qnum[m]; i++)
{
if (abs(Q[m][i]-400) < min) min = abs(Q[m][i]-400);
}
if (f[m][400+min] > f[m][400-min]) min = min+400; //选最小差值中总分和最大的
else min = 400-min;
printf("Jury #%d\n", casenum++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",
(min-400+f[m][min])/2, (400-min+f[m][min])/2);
for (i=0; i<m; i++) //从后往前依次找被选中的m个人
{
ans[i] = path[m-i][min];
min -= p[ans[i]]-d[ans[i]];
}
qsort(ans, m, sizeof(int), compare);
for (i=0; i<m; i++)
printf(" %d", ans[i]);
printf("\n\n");
}
}
相关文章推荐
- poj-2979-陪审团的人选-C语言-动态规划
- ACM POJ 1015 Jury Compromise(陪审团的人选,动态规划题,难)
- POJ 1015 公正陪审团问题 动态规划
- POJ 1015 公正陪审团问题 动态规划
- poj 1015 陪审团
- poj 1015 动态规划 难
- POJ 1015 Jury Compromise (动态规划)
- poj 1015 Jury Compromise 动态规划
- poj1015 背包/动态规划(Special Judge,Special Love)
- POJ 1015-Jury Compromise动态规划
- poj1015 动态规划
- POJ 2979 陪审团的人选 解题报告
- POJ 1015 动态规划
- [poj]动态规划1015
- OpenJudge 2979 陪审团的人选 / Poj 1015 Jury Compromise
- poj 1015 选配陪审团(对于维度中有负数的情况)
- OpenJudge 2979 陪审团的人选 / Poj 1015 Jury Compromise
- Jury Compromise(陪审团的人选、动态规划题)
- K - Jury Compromise POJ 1015 (动态规划 --难)
- poj 1015 dp(陪审团成员的选择)