Tinamei
其实你不知道你不知道

奔小康赚大钱

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5598    Accepted Submission(s): 2457

Problem Description
传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
 
Input
输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。
 
Output
请对每组数据输出最大的收入值,每组的输出占一行。
 
Sample Input
2
100 10
15 23
 
Sample Output
123
 
Source
 
题意:每家对每间房子有一个费用,怎么分配可以让总的费用最大。
KM
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 #define N 330
 9 #define INF 0xfffffff
10 
11 int n, s[N];
12 int lx[N], ly[N], maps[N][N], used[N], visx[N], visy[N];
13 
14 int found(int u)
15 {
16     visx[u] = true;
17     for(int i = 1; i <= n; i++)
18     {
19         if(!visy[i] && lx[u] + ly[i] == maps[u][i])
20         {
21             visy[i] = 1;
22             if(!used[i] || found(used[i]))
23             {
24                 used[i] = u;
25                 return true;
26             }
27         }
28         else
29             s[i] = min(s[i], lx[u]+ly[i]-maps[u][i]);
30     }
31     return false;
32 }
33 
34 int KM()
35 {
36     memset(used, 0, sizeof(used));
37     memset(lx, 0, sizeof(lx));
38     memset(ly, 0, sizeof(ly));
39 
40     for(int i = 1; i <= n; i++)
41         for(int j = 1; j <= n; j++)
42         lx[i] = max(lx[i], maps[i][j]);   // 每个lx存的是可以的最大值,ly是0,相加就是自己所投的资金最大值。
43     for(int i = 1; i <= n; i++)
44     {
45         for(int j = 1; j <= n; j++)
46             s[j] = INF;
47         while(1)
48         {
49             memset(visx, 0, sizeof(visx));
50             memset(visy, 0, sizeof(visy));
51 
52             if(found(i)) 
53                 break;
54             int d = INF;
55             for(int j = 1; j <= n; j++)
56                 if(!visy[j])
57                     d = min(d, s[j]);   // 如果找不到最大值匹配,就找需要减得最小值,让该匹配的减去最小值完成最大匹配
58             for(int j = 1; j <= n; j++)
59             {
60                 if(visx[j])
61                     lx[j] -= d;
62                 if(visy[j])
63                     ly[j] += d;
64             }
65         }
66     }
67     int ans = 0;
68     for(int i = 1; i <= n; i++)
69         ans += maps[used[i]][i];
70     return ans;
71 }
72 
73 int main()
74 {
75     while(~scanf("%d", &n))
76     {
77         for(int i = 1; i <= n; i++)
78         {
79             for(int j = 1; j <= n; j++)
80             {
81                 scanf("%d", &maps[i][j]);
82             }
83         }
84         printf("%d\n", KM());
85     }
86     return 0;
87 }

 

posted on 2015-09-08 16:52  Tinamei  阅读(206)  评论(0编辑  收藏  举报