学习原博客-----》》》》https://www.cnblogs.com/wenruo/p/5264235.html
入门题:::hdu2255
奔小康赚大钱
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 18527 Accepted Submission(s): 7827
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
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
//说明:此题主动方在房子,被动方是人
int price[301][301];//price[i][j]表示人i和房子j之间建立的价格值
int person[301],home[301];//期望值
bool vis_person[301];//人i有没有被访问过
bool vis_home[301];//房子j有没有被访问过
int match[301];//match[i]=u;人i已经被安排到房子u中
int slack[301];//记录每个人能被安排到房子中最小能增加的期望值
int n;
bool dfs(int u){
vis_home[u]=true;
for(int i=1;i<=n;i++){
if(vis_person[i])continue;//每一轮匹配,每个人只被'尝试'安排一次
int gap=home[u]+person[i]-price[i][u];
if(gap==0){//如果符合要求(期望值之和等于之间价格值)
vis_person[i]=true;//访问标记
if(match[i]==-1||dfs(match[i])){//之前没有被安排到房子中去,否则检测其匹配的房子能不能安排进别的人去
match[i]=u;//安排到房子u中
return true;
}
}//否则更新该人要想能安排到房子中所能增加的最小的期望值
else slack[i]=min(slack[i],gap);
}
//如果该房子未找到,返回false
return false;
}
int KM(){
memset(match,-1,sizeof(match));//初始化都未匹配到
memset(person,0,sizeof(person));//初始化每个人的期望值都为零
//每个房子的期望值为左右人对该房子的出价中的最大值
for(int i=1;i<=n;i++){
home[i]=price[1][i];
for(int j=2;j<=n;j++){
home[i]=max(home[i],price[j][i]);
}
}
//为每个房子安排人
for(int i=1;i<=n;i++){
memset(slack,INF,sizeof(slack));//要找最小值,便初始化无穷大
//为房子i安排人
while(1){
//每一轮匹配时都未访问过
memset(vis_home,false,sizeof(vis_home));
memset(vis_person,false,sizeof(vis_person));
if(dfs(i))break;//如果可以匹配到,break,未下一个房子安排人
int d=INF;//如果找不到,就降低home的期望值
//找最小可降低的期望值
for(int i=1;i<=n;i++){
//已经被安排的人不用做参考
if(!vis_person[i])d=min(d,slack[i]);
}
for(int i=1;i<=n;i++){
//所有访问过的房子降低期望值
if(vis_home[i])home[i]-=d;
//所有访问过的人增加期望值
if(vis_person[i])person[i]+=d;
//没有访问过的人,因为房子的期望值的降低,应容易被安排到房子
else slack[i]-=d;//最小可增加的期望值减小
}
}
}
//匹配完成,累加匹配成功的价格值
int res=0;
for(int i=1;i<=n;i++){
res+=price[i][match[i]];
}
return res;
}
int main(){
int x;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&x);
price[i][j]=x;
}
}
cout<<KM()<<endl;
}
return 0;
}
// /\ | / |**、
// / \ | / | \
// / \ |/ | / _____ ____ | /
// /------\ |\ |__/ / \ \ /\ / / \ | /
// / \ | \ | / \ \ / \ / /______\ |/
// / \ | \ | \ / \ / \ / \ |
// / \ | \ | \_____/ \/ \/ \_____ |
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//