POJ 1015 动态规划

找准状态 然后就是考研代码能力了。

给你n,m,让你在n个人里找m个人,使这m个人的两数之差最小,如有多解就输出最大和的那个。

dp[j][k]表示挑选j个人且差为k时的最大和。因为数据不大这样搞又简单又方便。

状态转移自然是:上一个点如果可以到达,就对这个点扫所有的已知数据,如果这个点没有出现过并且加上差之后还大,就是可转移的。

没有出现过用path[j][k]记录上一个最优解。

然后复杂度是赤裸裸的n^4............

感觉有点像当年不会写母函数然后做那个天平平衡那种类型的感觉,转移起来还是挺简单的。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[30][1000];
int path[30][1000];
int P[300],D[300];
int Ans[30];
int icase=0;
int main()
{
    int n,m;
    while (scanf ("%d%d",&n,&m)&&n&&m)
    {
        for (int i=1; i<=n; i++)
        {
            scanf ("%d%d",&P[i],&D[i]);
        }
        memset(dp,-1,sizeof(dp));
        memset(path,0,sizeof(path));
        int minscore=m*20;
        dp[0][minscore]=0;
        for (int j=0; j<m; j++)
        {
            for (int k=0; k<=minscore*2; k++)
            {
                if (dp[j][k]!=-1)
                {
                    for (int i=1; i<=n; i++)
                    {
                        if (dp[j][k]+P[i]+D[i]>dp[j+1][k+P[i]-D[i]])
                        {
                            int t1=j,t2=k;
                            t1=j;
                            t2=k;
                            while (t1>0&&path[t1][t2]!=i)
                            {
                                t2-=P[path[t1][t2]]-D[path[t1][t2]];
                                t1--;
                            }
                            if (t1==0)
                            {
                                dp[j+1][k+P[i]-D[i]]=dp[j][k]+P[i]+D[i];
                                path[j+1][k+P[i]-D[i]]=i;
                            }
                        }
                    }
                }
            }
        }
        int zhong=minscore;
        int pian=0;
        int pos;
        while (dp[m][zhong+pian]==-1&&dp[m][zhong-pian]==-1) pian++;
        if (dp[m][zhong+pian]>dp[m][zhong-pian]) pos=zhong+pian;
        else pos=zhong-pian;
        printf ("Jury #%d\n",++icase);
        printf ("Best jury has value %d for prosecution and value %d for defence:\n",(dp[m][pos]+pos-minscore)/2,(dp[m][pos]-pos+minscore)/2);
        int top=0,t1=m,t2=pos;
        while (t1>0)
        {
            Ans[top++]=path[t1][t2];
            t2-=P[path[t1][t2]]-D[path[t1][t2]];
            t1--;
        }
        sort(Ans,Ans+top);
        int flag=1;
        for (int i=0; i<top; i++)
        {
            if (flag)flag=0;
            else printf (" ");
            printf ("%d",Ans[i]);
        }
        printf ("\n\n");
    }
    return 0;
}

posted on 2016-04-17 11:24  very_czy  阅读(150)  评论(0编辑  收藏  举报

导航