• poj1015陪审团——DP+路径记录


    题目:http://poj.org/problem?id=1015

    DP的第一维是选了几个人,第二维是当前D与P的差值,而值存的是当前D与P的和;

    技巧1:通过平移避免负角标,即代码中的fix;

    技巧2:做完DP后找出最小的差的绝对值时,如下的那一小段代码很有效率;

    技巧3(*):记录路径——①更新路径时每次判断是否重复选了一个人,重复则不更新;

    if(f[j][k]+P[i]+D[i]>f[j+1][k+P[i]-D[i]])
    {
        t1=j;t2=k;
        while(t1>0&&Path[t1][t2]!=i)//验证i是否在前面出现过
        {
            t2-=P[Path[t1][t2]]-D[Path[t1][t2]];
            t1--;
        }
        if(t1==0)
        {
            f[j+1][k+P[i]-D[i]]=f[j][k]+P[i]+D[i];
            Path[j+1][k+P[i]-D[i]]=i;
        }         
    } 
    记录路径1(转)
            int tmp=mk;
            for(int j=m;j>0;j--)
            {
                int pr=pre[j][tmp];
                ans[j]=pr;
                tmp-=(a[pr]-b[pr]);
            }
            sort(ans+1,ans+m+1);
    记录路径1配套输出

                 ②使用vector,每次更新暴力复制;(下面采用)

    if(dp[i+1][j+subtraction[k]] <= dp[i][j] + _plus[k])  
    {  
        dp[i+1][j+subtraction[k]] = dp[i][j] + _plus[k];  
        path[i+1][j+subtraction[k]] = path[i][j];//每次更新都要把path全部复制过来,就是因为这个才用的vector  
        path[i+1][j+subtraction[k]].push_back(k);  
    } 
    记录路径2(转)

    注意:(不知为何)DP顺序,必须是i+1被i更新,原来写的是i被i-1更新,一直WA。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int n,m,a[205],b[205],f[25][805],fix,t,ans[205];
    vector<int>pre[25][805];
    int main()
    {
        while(scanf("%d%d",&n,&m)==2)
        {
            t++;
            memset(f,-1,sizeof f);
            memset(ans,0,sizeof ans);
            memset(pre,0,sizeof pre);
            if(!n&&!m)return 0;
            for(int i=1;i<=n;i++)
                scanf("%d%d",&a[i],&b[i]);
            fix=20*m;
    //        for(int k=0;k<=2*fix;k++)f[0][k]=0;
            f[0][fix]=0;
            for(int i=1;i<=n;i++)//第i个人 
                for(int j=m-1;j>=0;j--)//选了j个 
                    for(int k=0;k<=2*fix;k++)
                    {
    //                    if(f[j-1][k-a[i]+b[i]]<0)continue;//
    //                    if(f[j][k]<f[j-1][k-a[i]+b[i]]+a[i]+b[i])
    //                    {
    //                        f[j][k]=f[j-1][k-a[i]+b[i]]+a[i]+b[i];
    ////                        pre[j][k]=i;
    //                        pre[j][k]=pre[j-1][k-a[i]+b[i]];
    //                        pre[j][k].push_back(i);
    //                    }
                        if(f[j][k] >= 0)  
                        {  
                            if(f[j+1][k+a[i]-b[i]]<=f[j][k]+a[i]+b[i])  
                            {  
                                f[j+1][k+a[i]-b[i]]=f[j][k]+a[i]+b[i] ;
                                pre[j+1][k+a[i]-b[i]]=pre[j][k];
                                pre[j+1][k+a[i]-b[i]].push_back(i);  
                            }  
                        }  
                    }
            int mk;
    //        for(int k=fix;k<=2*fix;k++)
    //            if(f[m][k]>0)
    //            {
    //                mk=k;break;
    //            }
    //        for(int k=fix;k>=0;k--)
    //        {
    //            if(fix-k>=mk-fix)break;
    //            if(f[m][k]>0)
    //            {
    //                mk=k;break;
    //            }
    //        }
            int j=0;
            while(f[m][fix-j]<0&&f[m][fix+j]<0)j++;
            if(f[m][fix-j]>f[m][fix+j])mk=fix-j;
            else mk=fix+j;
            int d=(f[m][mk]+(mk-fix))/2;
            int p=(f[m][mk]-(mk-fix))/2;
    //        int tmp=mk;
    //        for(int j=m;j>0;j--)
    //        {
    //            int pr=pre[j][tmp];
    //            ans[j]=pr;
    //            tmp-=(a[pr]-b[pr]);
    //        }
    //        sort(ans+1,ans+m+1);
            printf("Jury #%d
    Best jury has value %d for prosecution and value %d for defence:
    ",t,d,p);
            for(int i=0;i<m;i++)
                printf(" %d",pre[m][mk][i]);
            printf("
    
    ");
        }
    }
  • 相关阅读:
    ORACLE设置用户密码不过期
    oracle错误(ORA:12154 ORA:01034 和 ORA:27101 ORA-18008 ORA-01081)
    常用正则表达式整理
    JS中处理单个反斜杠(即转义字符的处理)
    SpringMVC 使用PUT请求遇到的问题小结
    Tomcat7 目录详解
    java对象之----(PO,VO,DAO,BO,POJO)
    Oracle使用触发器和mysql中使用触发器的比较
    Oracle 数据库中对记录进行分页处理
    PHPOffice下PHPWord生成Word2007(docx)使用方法
  • 原文地址:https://www.cnblogs.com/Zinn/p/8571061.html
Copyright © 2020-2023  润新知