您的位置:首页 > 其它

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");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  path im