排位赛dp总结(HDU 2955,HDU 1864,HDU 1421)

 HDU2955:做这道题是,错误的认为题目所给的浮点型的数据都是精确到小数点后两位,然后把概率放大100倍,转换成为熟悉的01背包。。faint。。经测试题目的数据可能达到0.00001,甚至比0.00001还小,,所以必须转换思路,,
于是转成以所有银行的总资产为背包容量V。。求最大的逃跑概率。。
注意:题目给我们的是被抓的概率,,而我们要求最大的逃跑率,需要去被抓的概率pi的补 ,即1-pi
只有逃跑率才会等于各个逃跑率之积,被抓的概率不会等于各个被抓的概率之积,,概率的知识,不多说。。
状态转移方程:dp[j] = max ( dp[j], dp[j-cost[i]] * weight[i])

double dp[10005];
int money[105];
double pj[105];

int main(){
    int t,kase=0;
    cin>>t;
    while(t--){
        kase++;
        double p;
        int n;
        scanf("%lf%d",&p,&n);
        p=1-p;
        int sum=0;
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++){
            double pp;
            scanf("%d%lf",&money[i],&pp);
            pj[i]=1-pp;
            sum+=money[i];
        }
        dp[0]=1;
        for(int i=0;i<n;i++){
            for(int j=sum;j>=money[i];j--) dp[j]=max(dp[j],dp[j-money[i]]*pj[i]);
        }
        for(int i=sum;i>=0;i--){
            if(dp[i]>=p){
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}
HDU1864:由于报销额是double型,所以我们把发票作为背包,对于每个发票,在可以选择报销或者不报销。dp[j]=max(dp[j],dp[j-1]+money[i]);就是说可以,报销J个发票所得到的最大经费,可以第j个是报销的,也可以是第j个不报销而最大经费是由前j-1个发票加上另外第i个发票的报销数额。。
double a[35];
double p[35];
int main(){
    double q;
    int n;
    while(scanf("%lf%d",&q,&n)&&n){
        int m;
        memset(a,0,sizeof(a));
        int count=0;
        for(int i=0;i<n;i++){
            scanf("%d",&m);
            int flag=0;
            double A=0,B=0,C=0;
            for(int j=0;j<m;j++){
                char c,d;
                double val;
                cin>>c>>d>>val;
                if(c=='A'||c=='B'||c=='C'){
                    if(val>600){
                        flag=1;
                        continue;
                    }
                    if(c=='A') A+=val;
                    else if(c=='B') B+=val;
                    else C+=val;
                }
                else{
                    flag=1;
                    continue;
                }
            }
            if(!flag&&A<=600&&B<=600&&C<=600&&A+B+C<=1000) p[count++]=A+B+C;
        }
        for(int i=0;i<count;i++){
            for(int j=count;j>=1;j--){
                if(a[j-1]+p[i]<=q) a[j]=max(a[j],a[j-1]+p[i]);
            }
        }
        double maxn=0;
        for(int i=1;i<=count;i++) if(a[i]>maxn) maxn=a[i];
        printf("%.2lf\n",maxn);
    }
    return 0;
}


HDU1421:先对a[]按小到大排序.设:dp[i][j]表示前 i 个物品中搬 j 对的最少疲劳度.
显然,当i==2*j时,dp[i][j]=dp[i-2][j-1]+(a[i]-a[i-1])^2
因为,当 (a1-a2)^2+(a3-a4)^2 <= (a1-a4)^2+(a3-a2)^2 ( a1<=a2<=a3<=a4 ).
当i>2*j时,dp[i][j]=min( dp[i-1][j] , dp[i-2][j-1]+(a[i]-a[i-1])^2 )

int a[2005];
int dp[2005][1005];
int main(){
    int n,k;
    while(cin>>n>>k){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        memset(dp,0,sizeof(dp));
        for(int i=2;i<=n;i++){
            for(int j=1;j<=i/2;j++){
                if(i==2*j) dp[i][j]=dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]);
                else dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]));
            }
        }
        printf("%d\n",dp[n][k]);
    }
    return 0;
}


你可能感兴趣的:(ACM)