7 33.333% Oh, I lose my dear seaco!
这里用费用流再做一遍,首先我们求出任意Si与Xj决斗时,你能获得的分值Wij. 下面网络流建图:
源点s编号0, S1到Sn编号1到n, X1到Xn编号n+1到2*n, 汇点t编号2*n+1.
源点s到任意Si点有边 (s, i, 1, 0)
任意Xi点到汇点t有边 (i+n, t, 1, 0)
如果Si与Xj决斗的解过为Wij分值,那么有下面两种情况:
i==j时, 有边(i ,j+n, 1, -Wij*(n+1)-1) (注意这里Wij取负数且乘以(n+1)且减一,取负数,是因为最终结果取反是你能获得的最大分数.减一是使得该原始决斗顺序能够得以保留.乘以(n+1)是因为把权值扩大n+1倍之后再+1最终的权值就算是+n了然后除以(n+1)还是能得到正真的分数值 )
i!=j时,有边(i,j+n,1,-Wij*(n+1) )
最终我们求最小费用的负数X即可. X%(n+1)就是我们保持原先决斗顺序的个数,X/(n+1)就是我们能获得的最终分数.,这题要注意最大值的给定,1<<30, 小了会超时
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N = 1e6+10;
const int M = 1000;
int head[M], cnt;
struct node
{
int from, to, cap, cost, next;
}p[N];
void add(int u,int v,int w,int z)
{
p[cnt].from=u, p[cnt].to=v, p[cnt].cap=w, p[cnt].cost=z, p[cnt].next=head[u], head[u]=cnt++;
p[cnt].from=v, p[cnt].to=u, p[cnt].cap=0, p[cnt].cost=-z, p[cnt].next=head[v], head[v]=cnt++;
return ;
}
int d[M], pre[M], vis[M];
const int inf = 1<<30;
int min_cost_flow(int s,int t,int f)
{
int res=0;
while(f>0)
{
queueq;
q.push(s);
for(int i=0;i<=t;i++) d[i]=inf;
memset(pre,-1,sizeof(pre));
memset(vis,0,sizeof(vis));
vis[s]=1, d[s]=0;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i!=-1;i=p[i].next)
{
int v=p[i].to;
if(d[v]>d[u]+p[i].cost&&p[i].cap>0)
{
d[v]=d[u]+p[i].cost;
pre[v]=i;
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
vis[u]=0;
}
if(d[t]==inf) return 0;
int flow=f;
for(int i=pre[t];i!=-1;i=pre[p[i].from])
{
flow=min(flow,p[i].cap);
}
res+=flow*d[t];
for(int i=pre[t];i!=-1;i=pre[p[i].from])
{
p[i].cap-=flow, p[1^i].cap+=flow;
}
f-=flow;
}
return res;
}
int v[N], h[N], pi[N], a[N], b[N];
int get(int x,int y)
{
int s1=h[x], s2=pi[y];
while(1)
{
s2-=a[x];
if(s2<=0) return v[x];
s1-=b[y];
if(s1<=0) return -v[x];
}
}
int main()
{
printf("%d\n",0x3f3f3f3f);
int n;
while(scanf("%d", &n)!=EOF&&n!=0)
{
memset(head,-1,sizeof(head));
cnt=0;
for(int i=1;i<=n;i++) scanf("%d", &v[i]);
for(int i=1;i<=n;i++) scanf("%d", &h[i]);
for(int i=1;i<=n;i++) scanf("%d", &pi[i]);
for(int i=1;i<=n;i++) scanf("%d", &a[i]);
for(int i=1;i<=n;i++) scanf("%d", &b[i]);
int s=0, t=2*n+2;
for(int i=1;i<=n;i++)
{
add(s,i,1,0);
add(n+i,t,1,0);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int s=get(i,j);
if(i==j) add(i,n+j,1,-s*(n+1)-1);
else add(i,n+j,1,-s*(n+1));
}
}
int x=-min_cost_flow(s,t,n);
int cnt1=(x%(n+1));
x/=(n+1);
double px=(1.0*cnt1)/(n);
if(x>0) printf("%d %.3lf%%\n",x,100*px);
else printf("Oh, I lose my dear seaco!\n");
}
return 0;
}