zoukankan      html  css  js  c++  java
  • HDU 4406 GPA

    GPA

    Time Limit: 1000ms
    Memory Limit: 32768KB
    This problem will be judged on HDU. Original ID: 4406
    64-bit integer IO format: %I64d      Java class name: Main
     
    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 3
    1 1 2
    50 60 90
    1 1 0
    1 0 1
    2 20 4
    1 1 1 1
    50 50 50 40
    1 1 1 0
    0 0 0 1
    0 0 0

    Sample Output

    2.757813
    0.000000

    Source

     
    解题:最小费用最大流,最大费用最大流
     我们求最长路,所以越大越先被选!
    为什么计算now - pre呢,因为分母是固定的,只要分子越大,GPA也就越大,我们贪心,优先选取使自己增幅大的,也就是now - pre增加大的。
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <climits>
      7 #include <vector>
      8 #include <queue>
      9 #include <cstdlib>
     10 #include <string>
     11 #include <set>
     12 #include <stack>
     13 #define LL long long
     14 #define pii pair<int,int>
     15 #define INF 0x3f3f3f3f
     16 using namespace std;
     17 const int maxn = 1000;
     18 struct arc {
     19     int to,flow,next;
     20     double cost;
     21     arc(int x = 0,int y = 0,double z = 0,int nxt = -1) {
     22         to = x;
     23         flow = y;
     24         cost = z;
     25         next = nxt;
     26     }
     27 };
     28 arc e[maxn<<2];
     29 int head[maxn],p[maxn],tot,S,T,n,k,m;
     30 bool in[maxn];
     31 double d[maxn];
     32 int credit[maxn],basic[maxn],can[maxn][maxn];
     33 void add(int u,int v,int flow,double cost) {
     34     e[tot] = arc(v,flow,cost,head[u]);
     35     head[u] = tot++;
     36     e[tot] = arc(u,0,-cost,head[v]);
     37     head[v] = tot++;
     38 }
     39 bool spfa() {
     40     for(int i = S; i <= T; ++i) {
     41         d[i] = 0;
     42         p[i] = -1;
     43         in[i] = false;
     44     }
     45     queue<int>q;
     46     q.push(S);
     47     while(!q.empty()) {
     48         int u = q.front();
     49         q.pop();
     50         in[u] = false;
     51         for(int i = head[u]; ~i; i = e[i].next) {
     52             if(e[i].flow && d[e[i].to] < d[u] + e[i].cost) {
     53                 d[e[i].to] = d[u] + e[i].cost;
     54                 p[e[i].to] = i;
     55                 if(!in[e[i].to]) {
     56                     in[e[i].to] = true;
     57                     q.push(e[i].to);
     58                 }
     59             }
     60         }
     61     }
     62     return p[T] > -1;
     63 }
     64 void solve() {
     65     while(spfa()) {
     66         int minF = INF;
     67         for(int i = p[T]; ~i; i = p[e[i^1].to])
     68             minF = min(minF,e[i].flow);
     69         for(int i = p[T]; ~i; i = p[e[i^1].to]) {
     70             e[i].flow -= minF;
     71             e[i^1].flow += minF;
     72         }
     73     }
     74 }
     75 double calc(int x,int w){
     76     return (4.0 - 3.0*(100 - x)*(100 - x)/1600.0)*w;
     77 }
     78 int main() {
     79     while(scanf("%d %d %d",&n,&k,&m),n||m||k) {
     80         memset(head,-1,sizeof(head));
     81         S = tot = 0;
     82         T = n + m + 1;
     83         int sum = 0;
     84         double ans = 0;
     85         for(int i = 1; i <= m; ++i){
     86             scanf("%d",credit+i);
     87             sum += credit[i];
     88         }
     89         for(int i = 1; i <= m; ++i)
     90             scanf("%d",basic+i);
     91         for(int i = 1; i <= n; ++i) {
     92             add(i+m,T,k,0);
     93             for(int j = 1; j <= m; ++j) {
     94                 scanf("%d",can[i]+j);
     95                 if(can[i][j]) add(j,i+m,k,0);
     96             }
     97         }
     98         for(int i = 1; i <= m; ++i) {
     99             int h = basic[i];
    100             if(h < 60) {
    101                 add(S,i,60 - basic[i],INF);
    102                 h = 60;
    103             }
    104             double pre = calc(h,credit[i]);
    105             for(++h; h <= 100; ++h){
    106                 double now = calc(h,credit[i]);
    107                 add(S,i,1,now - pre);
    108                 pre = now;
    109             }
    110         }
    111         solve();
    112         for(int i = head[S]; ~i; i = e[i].next)
    113             basic[e[i].to] += e[i^1].flow;
    114         bool flag = true;
    115         for(int i = 1; i <= m; ++i){
    116             if(basic[i] < 60){
    117                 flag = false;
    118                 break;
    119             }
    120             ans += calc(basic[i],credit[i])/sum;
    121         }
    122         printf("%.6f
    ",flag?ans:0);
    123     }
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    【CFD之道】2018年原创文章汇总
    【OpenFOAM案例】03 Docker安装OpenFOAM
    【OpenFOAM案例】02 自己动手
    【OpenFOAM案例】01 elbow
    Fluent动网格【13】:网格光顺总结及实例
    Fluent动网格【12】:扩散光顺
    Fluent动网格【10】:区域运动案例
    Fluent动网格【11】:弹簧光顺
    happyChat开发系列:使用websocket.io实现双向通信的乐聊大前端开发
    vue,vuex的后台管理项目架子structure-admin,后端服务nodejs
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4125367.html
Copyright © 2011-2022 走看看