hdu 4406 GPA(最大费用流)
来源:互联网 发布:陶瓷内胆有毒吗 知乎 编辑:程序博客网 时间:2024/04/29 12:43
题意:距离考试有n天,现在有m个科目要复习,每天能有k个复习时间单元,每用一个时间单元复习,就能让所复习的科目分数增加一分,在保证不挂科的情况下,让绩点尽量高……
思路:这题除了费用的问题外,建图还是比较直观的,添加一个源点S和汇点T,每一天向T连一条容量为k,费用为0的弧,每个科目向对应能复习的天连一条容量为k,费用为0的弧,剩下就是S向科目连对应的弧。首先,为了保证不挂科,如果第i科基础分数小于60分,那么就从S向i连一条容量为60-分数,费用为inf的弧,这样在执行费用流的时候会优先填满这些弧,对于其他的分数x,我们可以算出x+1时增加的绩点,设f(x)为x对应的绩点的话,可以算一下f(x+1)-f(x),发现这是个减函数,因此,我们只需要对应会增加的分数,每一分连一条容量为1,费用为f(x)-f(x-1)的弧就好了。最后做一下最大费用流,其实这样建图也不会有环,因此费用取反做最小费用流也一样,最后检查一下是否还是有科目会挂就好了。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<set>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100+10;const int maxm=4000+10;struct Edge{ int from,to,cap,flow,next; double cost; Edge(){}; Edge(int ff,int tt,int cc,int fl,double co,int nx) {from=ff;to=tt;cap=cc;flow=fl;cost=co;next=nx;}}edges[maxm<<1];int head[maxn],a[maxn],p[maxn],nEdge;bool inq[maxn];double d[maxn];void AddEdges(int from,int to,int cap,double cost){ edges[++nEdge]=Edge(from,to,cap,0,cost,head[from]); head[from]=nEdge; edges[++nEdge]=Edge(to,from,0,0,-cost,head[to]); head[to]=nEdge;}bool spfa(int s,int t,int &flow,double &cost){ memset(inq,0,sizeof(inq)); memset(d,0,sizeof(d)); a[s]=inf;p[s]=0; queue<int>q; q.push(s); while(!q.empty()) { int u=q.front();q.pop(); inq[u]=false; for(int k=head[u];k!=-1;k=edges[k].next) { Edge e=edges[k]; if(e.cap>e.flow&&d[e.to]<d[u]+e.cost) { d[e.to]=d[u]+e.cost; a[e.to]=min(a[u],e.cap-e.flow); p[e.to]=k; if(!inq[e.to]){inq[e.to]=true;q.push(e.to);} } } } if(d[t]==0) return false; flow+=a[t]; cost+=a[t]*d[t]; int u=t; while(u!=s) { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; u=edges[p[u]].from; } return true;}void mincost(int s,int t){ int flow=0;double cost=0; while(spfa(s,t,flow,cost)) ;}int basicp[maxn],w[maxn],matrix[maxn][maxn],res[maxn];double getpoint(int i,int x){ return (4.0-3.0*(100-x)*(100-x)/1600.0)*w[i];}double solve(int S,int m){ double ans=0; memset(res,0,sizeof(res)); for(int k=head[S];k!=-1;k=edges[k].next) { Edge e=edges[k]; res[e.to]+=e.flow; } for(int i=1;i<=m;++i) { res[i]+=basicp[i]; if(res[i]<60) return 0; ans+=getpoint(i,res[i]); } return ans;}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,k,m; while(~scanf("%d%d%d",&n,&k,&m)) { if(n==0&&k==0&&m==0) break; memset(head,0xff,sizeof(head)); nEdge=-1; for(int i=1;i<=m;++i) scanf("%d",&w[i]); for(int i=1;i<=m;++i) scanf("%d",&basicp[i]); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",&matrix[i][j]); int S=0,T=n+m+1,sum=0; for(int i=1;i<=m;++i) { if(basicp[i]<60) AddEdges(S,i,60-basicp[i],1e6); int j=max(basicp[i],60)+1; for(;j<=100;++j) AddEdges(S,i,1,getpoint(i,j)-getpoint(i,j-1)); for(j=1;j<=n;++j) if(matrix[j][i]) AddEdges(i,m+j,k,0); sum+=w[i]; } for(int i=1;i<=n;++i) AddEdges(m+i,T,k,0); mincost(S,T); double ans=solve(S,m)/sum; printf("%.6lf\n",ans); } return 0;}
0 0
- hdu 4406 GPA 最大费用最大流
- hdu 4406 GPA(最大费用流)
- 【HDU】4406 GPA 最大费用流
- HDU 4406 GPA 最大费用流
- HDU 4406 GPA 最大费用流
- HDU 4406 GPA(网络流-最大费用流)
- hdu 4406 GPA 费用流
- HDU 4406 - GPA(网络流‘费用流)
- hdu 4406 GPA(费用流)
- HDU 4406 GPA(费用流)
- HDU 4406 GPA(费用流)
- hdu 4406 #最大费用流
- hdu 4968 最大最小gpa
- hdu 4322 最大费用最大流
- hdu 2686 Matrix 最大费用最大流
- hdu 4322(最大费用最大流)
- hdu 4322 Candy 最大费用最大流
- Matrix (hdu 2686 最大费用最大流)
- Hadoop个版本区别
- yum install bzr error
- Shell的入门
- 关于海滩争霸Crab代码的理解
- Makefile编写规则
- hdu 4406 GPA(最大费用流)
- 能从点(1,1)跳到点(a,b)吗
- Ubuntu编译Wireshark
- 微信公众平台博客
- char、nchar、varchar、nvarchar、text、ntext的区别
- dwr WebContextFactory 工厂模式
- VS2005启动调试器很慢的解决办法
- ios项目生成ipa文件的真正简单可用的方法
- OpenCV形态学操作