飞扬的小鸟
来源:互联网 发布:中国税务报网络报检索 编辑:程序博客网 时间:2024/05/01 21:03
题目描述
Flappy Bird是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败。
现在小鸟们遇到了一个难题,他们遇到了一堵巨大的墙,墙上仅有m个洞供他们通过,由于小鸟们的体型不同且墙上洞的形状也不同,所以每种体型的鸟通过每个洞的时间都不同,鸟的体型共有n种,第i种体型的鸟通过第j个洞需要的时间记为T(i,j),且一个洞必须前一只鸟通过之后后一只鸟才能开始通过。
从时刻0开始,鸟开始通过,而每一只鸟的等待时间为从时刻0到自己已经通过洞的时间。现在知道了第i种体型的鸟有pi只,请求出使所有鸟都通过墙的最少的等待时间之和。
网络流
显然的思路,用网络流做。
对每个洞拆点,i.j表示第i个洞被通过这个洞的倒数第j只鸟通过。
然后连边跑费用流。
然而边数太多直接爆炸,怎么办?
注意到i.j没被流i.j+1就绝不可能被流。
因此动态加边,初始只连所有到x.1的。
目前连到x.y,流成功一次加上所有到x.y+1的边。
然后莫名很慢,所以这里本辣鸡加上了对只有一个洞的特判(面向数据编程)
#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=100000+10,maxm=7000000+10,inf=1000000000;int h[maxn],d[maxn],now[maxn],go[maxm],dis[maxm],co[maxm],fx[maxm],next[maxm];int id[150][850],di[150*850+10][2],time[50][150],a[50],w[850];bool bz[maxn];int i,j,k,l,r,s,t,n,m,p,tot,top,ans,last;void add(int x,int y,int z,int c,int d){ go[++tot]=y; dis[tot]=z; co[tot]=c; fx[tot]=tot+d; next[tot]=h[x]; h[x]=tot;}int dfs(int x,int flow,int las,int cost){ if (x==t){ ans+=flow*cost; last=las; return flow; } bz[x]=1; int r=now[x],k; while (r){ if (!bz[go[r]]&&dis[r]&&d[x]==d[go[r]]+co[r]){ k=dfs(go[r],min(flow,dis[r]),x,cost+co[r]); if (k){ dis[r]-=k; dis[fx[r]]+=k; now[x]=r; return k; } } r=next[r]; } return now[x]=0;}bool change(){ int tmp=inf,i,r; fo(i,s,t) if (bz[i]){ r=h[i]; while (r){ if (!bz[go[r]]&&dis[r]&&d[go[r]]+co[r]-d[i]<tmp) tmp=d[go[r]]+co[r]-d[i]; r=next[r]; } } if (tmp==inf) return 0; fo(i,s,t) if (bz[i]) d[i]+=tmp; return 1;}int read(){ int x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x;}int main(){ n=read();m=read(); fo(i,1,n) a[i]=read(),p+=a[i]; fo(i,1,n) fo(j,1,m) time[i][j]=read(); if (m==1){ top=0; fo(i,1,n) fo(j,1,a[i]) w[++top]=time[i][1]; sort(w+1,w+p+1); fo(i,1,p) ans+=w[i]*(p-i+1); printf("%d\n",ans); return 0; } s=1;t=p*m+n+2; fo(i,1,n){ add(s,i+1,a[i],0,1); add(i+1,s,0,0,-1); } top=n+1; fo(i,1,m) fo(j,1,p){ id[i][j]=++top; di[top][0]=i; di[top][1]=j; if (j==1) fo(k,1,n){ add(k+1,id[i][j],1,time[k][i]*j,1); add(id[i][j],k+1,0,-time[k][i]*j,-1); } if (j<=p){ add(id[i][j],t,1,0,1); add(t,id[i][j],0,0,-1); } } do{ fo(i,s,t) now[i]=h[i]; fill(bz+s,bz+t+1,0); while (dfs(s,inf,-1,0)){ r=id[di[last][0]][di[last][1]+1]; fo(i,1,n){ add(i+1,r,1,time[i][di[last][0]]*(di[last][1]+1),1); add(r,i+1,0,-time[i][di[last][0]]*(di[last][1]+1),-1); } fill(bz+s,bz+t+1,0); } }while (change()); printf("%d\n",ans);}
0 0
- NOIP2014 飞扬的小鸟
- NOIP2014飞扬的小鸟
- NOIP2014飞扬的小鸟
- 飞扬的小鸟
- NOIP2014 飞扬的小鸟
- noip2014飞扬的小鸟
- JZOJ4716. 飞扬的小鸟
- 飞扬的小鸟
- 飞扬的小鸟
- 【NOIP2014】飞扬的小鸟
- 飞扬的小鸟
- noip2014飞扬的小鸟
- 飞扬的小鸟 noip2014
- NOIP2014 飞扬的小鸟
- [noip2014tg] 飞扬的小鸟
- [NOIP2014]飞扬的小鸟
- [NOIP2014] 飞扬的小鸟
- 【NOIP2014】飞扬的小鸟
- 【LeetCode】minimum-path-sum
- JAVA面试宝典10
- 下面代码出现错误:[下面的框架可能不正确和/或缺失,没有为 kernel32.dll 加载符号],请问是怎么回事啊?
- poj 1155 TELE 树形背包dp
- 25 最长最短单词
- 飞扬的小鸟
- 注入新密钥的步骤
- masnory 基本使用
- JAVA数组的使用
- 初识ElasticSearch
- python将多个变量输入到文件
- 我的Unity 3D之旅——第一人称射击游戏(6)
- ubuntu 下载工具uget+aria2
- ubuntu终端路径太长