HDU 4406 GPA(网络流-最大费用流)

来源:互联网 发布:淘宝开店钱盾认证 编辑:程序博客网 时间:2024/05/16 08:10

GPA


Problem Description
GPA(Grade-Point Average) is one way to measure students’ academic performance in PKU. Each course has an integer credit, ranges from 1 to 99. For each course, you will get a score at the end of the semester, which is an integer ranges from 0 to 100. Then you can calculate the Grade-Point of this course with the following formula. (Your score is x and your Grade-Point is p, using real arithmetic)

Then you can get the GPA with the following formula (the Grade-Point of course i is pi, and the credit of course i is wi).

Now it is not far from the final exam, if you do not review, you can only get a basic score in each course.

You have n days to review. There are K classes in each day. For each class, only one course can be reviewed. After the review, your score in this course will exactly increase by 1. You can get more increment by spending more classes in this course. But the score may not exceed 100.

For some reasons, not any course can be reviewed in any class. Each day you can only review some of the courses.

Now you want your GPA to be as high as possible, and at the same time, you do not want to fail in any course. Please calculate the highest GPA you can get. 
 

Input
The input consists of several test cases. Each test case begins with 3 integers N (0<=N<=40), K(0<K<=20), M (0<M<=20), representing the number of days, the number of classes in each day and the number of courses. Next line contains M integers representing credits of each course and M integers representing basic scores of each course (0<=score<=100). Next N lines contain an N*M matrix, the jth element in ith row means whether you can review course j in ith day, 1 means you can review course j in ith day, 0 means you cannot. The Input ends with 0 0 0.
 

Output
For each test case, output the highest possible GPA, round to 6 digits after decimal point. If you have to fail a course, output 0.000000 instead.
 

Sample Input
2 10 31 1 250 60 901 1 01 0 12 20 41 1 1 150 50 50 401 1 1 00 0 0 10 0 0
 

Sample Output
2.7578130.000000
 

Source
2012 ACM/ICPC Asia Regional Jinhua Online
 

Recommend
zhoujiaqi2010   |   We have carefully selected several similar problems for you:  4934 4933 4932 4931 4930 
 

题目大意:

有m门课,n天,每天可以复习特定的几门课,每门课有学分,基础分,复习一次可以加分,绩点有计算公式,问你总绩点最多多少?


解题思路:

用最大费用流可以做。

解题代码:

#include <iostream>#include <cstdio>#include <queue>#include <cstring>#include <cstdlib>#include <algorithm>using namespace std;const int maxn=11000;const int maxm=1100000;const double inf=1e8;struct edge{    int u,v,next,f;    double c;    edge(int u0=0,int v0=0,int f0=0,double c0=0,int next0=0){        u=u0,v=v0,f=f0,c=c0,next=next0;    }}e[maxm];int head[maxn],path[maxn];double dist[maxn];bool visited[maxn];int cnt,src,sink;void init(){    cnt=0;    memset(head,-1,sizeof(head));}void adde(int u,int v,int f,double c){    e[cnt].u=u,e[cnt].v=v,e[cnt].f=f,e[cnt].c=c,e[cnt].next=head[u],head[u]=cnt++;    e[cnt].u=v,e[cnt].v=u,e[cnt].f=0,e[cnt].c=-c,e[cnt].next=head[v],head[v]=cnt++;}bool bfs(){     for(int i=src;i<=sink;i++){        dist[i]=-inf;        path[i]=-1;     }     dist[src]=0;     queue <int> q;     q.push(src);     visited[src]=true;     while(!q.empty()){         int s=q.front();         q.pop();         for(int i=head[s];i!=-1;i=e[i].next){              int d=e[i].v;              if(e[i].f>0 && dist[s]+e[i].c>dist[d]){                 dist[d]=dist[s]+e[i].c;                 path[d]=i;                 if(!visited[d]){                    visited[d]=true;                    q.push(d);                 }              }         }         visited[s]=false;     }     return path[sink]>=0;}double getMaxCost(){    //int maxflow=0;    double ret=0;    while(bfs()){        int delta=inf;        for(int i=sink;i!=src;i=e[path[i]].u){            if( e[path[i]].f<delta ) delta=e[path[i]].f;        }        for(int i=sink;i!=src;i=e[path[i]].u){            e[path[i]].f-=delta;            e[path[i]^1].f+=delta;        }        ret+=dist[sink]*delta;        //maxflow+=delta;    }    //cout<<"maxflow:"<<maxflow<<endl;    return ret;}int nd,nf,nc;int fen[50],base[50],flag[50][50];const double eps=1e-6;void input(){    for(int i=0;i<nc;i++) scanf("%d",&fen[i]);    for(int i=0;i<nc;i++) scanf("%d",&base[i]);    for(int i=0;i<nd;i++){        for(int j=0;j<nc;j++){            scanf("%d",&flag[i][j]);        }    }}double getf(double x){    return 4-3*(100-x)*(100-x)/1600.0;}void build(){    init();    src=0,sink=nc+nd+1;    for(int i=0;i<nc;i++){        if(base[i]<60){            adde(src,i+1,60-base[i],inf);            for(int t=60;t<100;t++){                adde(src,i+1,1, ( getf(t+1)-getf(t) )*fen[i] );            }        }else{            for(int t=base[i];t<100;t++){                adde(src,i+1,1, ( getf(t+1)-getf(t) )*fen[i] );            }        }    }    for(int i=0;i<nd;i++){        for(int j=0;j<nc;j++){            if(flag[i][j]){                adde(j+1,nc+i+1,nf,0);            }        }    }    for(int i=0;i<nd;i++){        adde(i+1+nc,sink,nf,0);    }}void solve(){    build();    double ans=getMaxCost();    for(int i=head[src];i!=-1;i=e[i].next){        if(e[i].f>0 && e[i].c>inf-eps){            printf("0.000000\n");            return;        }    }    int sum=0;    for(int i=0;i<nc;i++) sum+=fen[i];    for(int i=0;i<nc;i++){        if(base[i]<60){            ans-=inf*(60-base[i]);            ans+=( getf(60)-getf(base[i]) )*fen[i];        }        ans+=getf(base[i])*fen[i];    }    printf("%.6lf\n",ans/sum);}int main(){    while(scanf("%d%d%d",&nd,&nf,&nc)!=EOF && (nd||nf||nc) ){        input();        solve();    }    return 0;}





2 0
原创粉丝点击