现在的位置: 首页 > 综合 > 正文

hdu 5045 Contest 2014 ACM/ICPC Asia Regional Shanghai Online

2018年04月25日 ⁄ 综合 ⁄ 共 2056字 ⁄ 字号 评论关闭

这一题开始没有注意 at any time,题目半天没看懂啥意思。 {1,1,3,2,3}是illegal的原因是在第三个同学做题时,1已经比2多做两题了。所以为了满足任意时刻做题数目不超过1,只能一轮一轮的做,就是[1,n]的时间段里,每个人都要做一题,就是1~n的全排列。

蒟蒻表示直接对M/N组每组做了N次,再对M%N做一次。但是大神们的另一种做法要方便很多,点击打开链接

dp[i][j],i表示当前学生的状态,用二进制数表示,每一位是1就表示这个学生做过题了,j表示做到了第几题。

这一题WA了几次==是因为状态转移到dp[(1<<N)-1][j]时,这一轮结束,下一轮的状态是从x=0开始的,所以前一轮x=(1<<N)-1时要将x=0。果真样例都是骗人的=。=

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include <ctype.h>
using namespace std;

//hdu 5045
int T;
int N;
int M;
double p[15][1010];
double dp[1<<11][1010];//dp[i][j] means the maximum probability, j is the number of submitted problems and i is the status of students
double ans;
void run()
{
    memset(dp,0,sizeof(dp));
    ans=0;
    dp[0][0]=0;
   // for(int i=0;i<N;i++) dp[1<<i][1]=p[i+1][1];
    int round=M/N;
    int remain=M%N;
  //  cout<<round<<" "<<remain<<endl;
    for(int r=0;r<round;r++)
    {
        for(int i=0;i<(1<<N);i++)
        {
            for(int k=0;k<N;k++)
            {
                if(i&(1<<k)) continue;
                int x=i|(1<<k);

                int cnt=0;
                for(int j=0;j<N;j++)
                {
                    if(x&(1<<j))
                    {
                        cnt++;//找出1的个数,代表此时几个人做题,即做了几题
                    }
                }
                if(x==(1<<N)-1) x=0;
            //    cout<<r*N+cnt<<" "<<hex<<x<<" "<<dp[x][r*N+cnt]<<endl;


                dp[x][r*N+cnt]=max(dp[x][r*N+cnt],dp[i][r*N+cnt-1]+p[k+1][r*N+cnt]);//求的是期望值,所以概率之间是相加关系:sum[1*p+0*(1-p)]
              //  cout<<dp[x][r*N+cnt]<<" "<<dp[i][r*N+cnt-1]<<" "<<k+1<<" "<<r*N+cnt<<" "<<hex<<x<<endl;
            }
        }
    }
    //dp[0][round*N]=dp[(1<<N)-1][round*N];
    for(int i=0;i<(1<<N);i++)
    {
        for(int k=0;k<N;k++)
        {
            if(i&(1<<k)) continue;
            int x=i|(1<<k);
            int cnt=0;
            for(int j=0;j<N;j++)
            {
                if(x&(1<<j))
                {
                    cnt++;
                    if(cnt>remain) continue;
                }
            }
             if(x==(1<<N)-1) x=0;
            dp[x][round*N+cnt]=max(dp[x][round*N+cnt],dp[i][round*N+cnt-1]+p[k+1][round*N+cnt]);
          //  cout<<dp[x][round*N+cnt]<<" "<<dp[i][round*N+cnt-1]<<" "<<k+1<<" "<<round*N+cnt<<" "<<hex<<x<<endl;
        }
    }
    for(int i=0;i<(1<<N);i++)
    {
        ans=max(ans,dp[i][M]);
    }
}
int main()
{
    freopen("input.txt","r",stdin);
   // freopen("data.txt","r",stdin);
   // freopen("out1.txt","w",stdout);
   memset(p,0,sizeof(p));
   scanf("%d",&T);
   for(int ca=1;ca<=T;ca++)
   {
       scanf("%d %d",&N,&M);
       for(int i=1;i<=N;i++)
       {
           for(int j=1;j<=M;j++)
           {
               scanf("%lf",&p[i][j]);
           }
       }
       run();
       printf("Case #%d: %.5lf\n",ca,ans);

   }
    return 0;
}

抱歉!评论已关闭.