标签:hdu
http://acm.hdu.edu.cn/showproblem.php?pid=4406
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
2.757813 0.000000
题意:有m科课程需要学习,每个课程有一个基础分数,每学习该课程一个时间单位,该课程的分数就增加1分。现在有n天的学习时间,每天有K个单位时间,并且每天可以学习的课程是固定的,给出学分绩点的计算方式,求可以达到的最高的学分绩点,要求所有课程都要及格。
分析:费用和流量平方成正比的最大费用最大流,大白p366有模型。
每天向汇点连边,流量为K,费用0;每门课向符合要求的天连边,流量K费用0。
源点向每门课连边,为了保证每门课及格,连向s<60分的课流量60-s,费用-INF,然后每门课连min(100-s,40)条流量为1费用为f(x,p)-f(x+1,p)的边,可以发现每条边的费用随着x增大是递增的(负的),这样就保证增广的时候是按分数依次的。这里的f值可以化为整数,就避免了处理精度。
跑最小费用最大流,然后计算每门课的基础上加上各自的流量,如果还有小于60输出0.
/** * @author neko01 */ //#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <string.h> #include <iostream> #include <algorithm> #include <queue> #include <vector> #include <cmath> #include <set> #include <map> using namespace std; typedef long long LL; #define min3(a,b,c) min(a,min(b,c)) #define max3(a,b,c) max(a,max(b,c)) #define pb push_back #define mp(a,b) make_pair(a,b) #define clr(a) memset(a,0,sizeof a) #define clr1(a) memset(a,-1,sizeof a) #define dbg(a) printf("%d\n",a) typedef pair<int,int> pp; const double eps=1e-9; const double pi=acos(-1.0); const int INF=0x3f3f3f3f; const LL inf=(((LL)1)<<61)+5; const int maxn=505; const int M=400010; struct Edge{ int to,next,cap,cost; Edge(int _to=0,int _next=0,int _cap=0,int _cost=0){ to=_to;next=_next;cap=_cap;cost=_cost; } }e[M]; int head[maxn],tol; int pre[maxn]; double dist[maxn]; bool vis[maxn]; int N; //点数 void init(int n) { N=n; tol=0; clr1(head); } void add(int u,int v,int cap,double cost) { e[tol]=Edge(v,head[u],cap,cost); head[u]=tol++; e[tol]=Edge(u,head[v],0,-cost); head[v]=tol++; } bool spfa(int s,int t) { queue<int>q; for(int i=0;i<=N;i++) { dist[i]=INF; vis[i]=false; pre[i]=-1; } dist[s]=0,vis[s]=true; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].to; if(e[i].cap&&dist[v]>dist[u]+e[i].cost) { dist[v]=dist[u]+e[i].cost; pre[v]=i; if(!vis[v]) vis[v]=true,q.push(v); } } } if(pre[t]==-1) return false; return true; } void mincostflow(int s,int t,int &flow,int &cost) { flow=cost=0; while(spfa(s,t)) { int Min=INF; for(int i=pre[t];i!=-1;i=pre[e[i^1].to]) if(Min>e[i].cap) Min=e[i].cap; for(int i=pre[t];i!=-1;i=pre[e[i^1].to]) e[i].cap-=Min,e[i^1].cap+=Min,cost+=e[i].cost*Min; flow+=Min; } } int w[25]; int sc[25]; int a[45][25]; int fun(int x,int w) { return (6400-3*(100-x)*(100-x))*w; } int main() { int n,k,m; while(~scanf("%d%d%d",&n,&k,&m)) { if(n==0&&k==0&&m==0) break; int sum=0; for(int i=1;i<=m;i++) { scanf("%d",&w[i]); sum+=w[i]; } for(int i=1;i<=m;i++) scanf("%d",&sc[i]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); int s=0,t=n+m+1; init(t+1); for(int i=1;i<=m;i++) { if(sc[i]<60) add(s,i,60-sc[i],-INF); int j=max(sc[i],60); int pre=fun(j,w[i]); for(j++;j<=100;j++) { int now=fun(j,w[i]); add(s,i,1,pre-now); pre=now; } for(j=1;j<=n;j++) if(a[j][i]) add(i,j+m,k,0); } for(int i=1;i<=n;i++) add(i+m,t,k,0); int flow,cost; mincostflow(s,t,flow,cost); for(int i=head[s];i!=-1;i=e[i].next) sc[e[i].to]+=e[i^1].cap; int ans=0,i; for(i=1;i<=m;i++) { if(sc[i]<60) break; ans+=fun(sc[i],w[i]); } if(i!=m+1) ans=0; printf("%.6lf\n",1.0*ans/sum/1600); } return 0; }
标签:hdu
原文地址:http://blog.csdn.net/neko01/article/details/40779983