【BZOJ 4819】 4819: [Sdoi2017]新生舞會 (0-1分數規劃、二分+KM)

4819: [Sdoi2017]新生舞會

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 601  Solved: 313

Description

學校組織了一次新生舞會,Cathy做爲經驗豐富的老學姐,負責爲同窗們安排舞伴。有n個男生和n個女生參加舞會
買一個男生和一個女生一塊兒跳舞,互爲舞伴。Cathy收集了這些同窗之間的關係,好比兩我的以前認識沒計算得出 
a[i][j] ,表示第i個男生和第j個女生一塊兒跳舞時他們的喜悅程度。Cathy還須要考慮兩我的一塊兒跳舞是否方便,
好比身高體重差異會不會太大,計算得出 b[i][j],表示第i個男生和第j個女生一塊兒跳舞時的不協調程度。固然,
還須要考慮不少其餘問題。Cathy想先用一個程序經過a[i][j]和b[i][j]求出一種方案,再手動對方案進行微調。C
athy找到你,但願你幫她寫那個程序。一個方案中有n對舞伴,假設沒對舞伴的喜悅程度分別是a'1,a'2,...,a'n,
假設每對舞伴的不協調程度分別是b'1,b'2,...,b'n。令
C=(a'1+a'2+...+a'n)/(b'1+b'2+...+b'n),Cathy但願C值最大。

Input

第一行一個整數n。
接下來n行,每行n個整數,第i行第j個數表示a[i][j]。
接下來n行,每行n個整數,第i行第j個數表示b[i][j]。
1<=n<=100,1<=a[i][j],b[i][j]<=10^4

Output

一行一個數,表示C的最大值。四捨五入保留6位小數,選手輸出的小數須要與標準輸出相等

Sample Input

3
19 17 16
25 24 23
35 36 31
9 5 6
3 4 2
7 8 9

Sample Output

5.357143

HINT

Source

 

【分析】ios

  好吧費用流居然給過。。。ide

  可是我打KM。。。算練一練吧。。。仍是打錯了兩個地方【要記住下次不要錯了啊!!!spa

  就是經典的0-1分數規劃code

  二分答案midblog

  則$\sum a[i][j]-mid*b[i][j]>=0$,這個用KM作最大費用判斷是否大於等於0便可。ip

  而後精度要弄小一點纔不會被卡,弄到了1e-10,而後狂T是由於INF不夠大,暈。。。get

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 #define Maxn 110
 9 const double eps=1e-10;
10 const double INF=1e12;
11 
12 double a[Maxn][Maxn],b[Maxn][Maxn];
13 
14 int visx[Maxn],visy[Maxn],match[Maxn];
15 double slack[Maxn],lx[Maxn],ly[Maxn];
16 int n;
17 
18 bool ffind(double mid,int x,int nt)
19 {
20     visx[x]=nt;
21     for(int y=1;y<=n;y++) if(visy[y]!=nt)
22     {
23         if(fabs(lx[x]+ly[y]-(a[x][y]-mid*b[x][y]))<eps)
24         {
25             visy[y]=nt;
26             if(!match[y]||ffind(mid,match[y],nt))
27             {
28                 match[y]=x;
29                 return 1;
30             }
31         }
32         else slack[y]=min(slack[y],lx[x]+ly[y]-(a[x][y]-mid*b[x][y]));
33     }
34     return 0;
35 }
36 
37 bool check(double mid)
38 {
39     for(int i=1;i<=n;i++) match[i]=0;
40     for(int i=1;i<=n;i++)
41     {
42         visx[i]=visy[i]=0;
43         lx[i]=-INF;ly[i]=0;
44         for(int j=1;j<=n;j++) lx[i]=max(lx[i],a[i][j]-mid*b[i][j]);
45     }int nt=0;
46     for(int i=1;i<=n;i++)
47     {
48         for(int j=1;j<=n;j++) slack[j]=INF;
49         while(1)
50         {
51             nt++;
52             if(ffind(mid,i,nt)) break;
53             double delta=INF;
54             for(int j=1;j<=n;j++) if(visy[j]!=nt) delta=min(delta,slack[j]);
55             for(int j=1;j<=n;j++)
56             {
57                 if(visx[j]==nt) lx[j]-=delta;
58                 if(visy[j]==nt) ly[j]+=delta;
59                 else if(fabs(INF-slack[j])<eps) slack[j]-=delta;
60             }
61         }
62     }
63     double ans=0;
64     for(int i=1;i<=n;i++) ans+=lx[i]+ly[i];
65     return ans>=0;
66 }
67 
68 int main()
69 {
70     double l=0,r=0;
71     scanf("%d",&n);
72     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&a[i][j]),r+=a[i][j];
73     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&b[i][j]);
74     while(r-l>eps)
75     {
76         double mid=(l+r)/2;
77         if(check(mid)) l=mid;
78         else r=mid;
79     }
80     printf("%.6lf\n",l);
81     return 0;
82 }
View Code

 

2017-04-28 13:21:57string

相關文章
相關標籤/搜索