传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1037

试题描述:

信息学社团已经逐渐发展壮大,成员也越来越多。现在,有n个同学有了关于信息学的问题,公务繁忙的杨老师决定派出n个小助手来帮助他们解答问题。现在问题来了,每个小助手和它对应的同学不能离的太远(要不然杨老师会觉得场面很乱…),也就是说两个人的距离不能超过杨老师的规定值Distance。同时,俩个人的中间不能隔有其他同学(要不然同学们会互相干扰的…),就是说在两个同学a,b所连成的线段上不能有同学c。现在,每解答一个问题(我们认为小助手足够聪明,只要有匹配的人都可以解答他们的问题),杨老师都会奖励小助手一些积分,现在,贪心的小助手们联合起来想让他们获取的积分总数尽量大…请你帮小助手们编写一个程序来算出他们能获得的最大的积分数。(一些题目补充见“其他说明”)

输入:

第一行是一个正整数Distance表示杨老师规定的最大范围。
第二行是一个正整数n,表示有n个同学。
接下来的n行是每个同学的x,y坐标及他们的名字。再接下来的n行是每个小助手的x,y坐标及他们的名字。
输入文件剩下的部分描述了一些同学与特定小助手解答完问题能获得的杨老师的奖励。每一行的格式为Name1 Name2 p。Name1和Name2为同学,小助手的姓名,p是他们之间的可以获得的积分。以一个End作为文件结束标志。每两个人之间的奖励积分如果被描述多次,则以最后一次的描述为准。如果没有被描述,则说明他们奖励积分为1。

输出:

一个正整数w,表示小助手们能获得的最多的积分数。

输入示例:

2 3
0 0 zYT
1 1 WJh
0 2 XYz
1 0 XJR
0 1 WZJ
1 2 LZJ
ZYt LZJ 100
WZJ XYZ 20
XYZ LZJ 40
WJH WzJ 5
WJH LZJ 30
XJR WJH 20
ZYT XJR 15
End

输出示例:

65

其他说明:

一些小问题:
首先:我们假设同学和小助手都不会移动……
其次:我们假设杨老师手中有无限积分……
然后:每个人的名字由于OI出现问题导致大小写随机了,你的程序需要能够正确识别纠错。(具体请看样例)
再然后:人们的姓名是长度小于200且仅包含字母的字符串(不是汉字)。
再再然后:保证给出的奖励分数合法,即小助手和小助手不会给出奖励值,同学和同学不会给出奖励值。
再再再然后:一个小助手只能帮助一个同学,一个同学只能被一个小助手帮助。
再再再再然后:最后的结果保证在int范围内。
最后声明:由于数据给的很小,时间卡紧了一点。

数据范围:
1 <= n < 30
1 <= Distance < 10^6
1 <= x,y < 10^6
1 <= p <= 1500
以上所有变量均属于整数集。

题解:

【裸体二分图最佳完美匹配】小助手和同学形成了天然的二分图。用向量判重线、预处理两点间距离平方判距离来连边。

KM的:

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; void read(int& x)
{
x = ;
int sig = ;
char ch = getchar(); while(!isdigit(ch))
{
if(ch == '-') sig = -;
ch = getchar();
} while(isdigit(ch))
{
x = * x + ch - '';
ch = getchar();
} x *= sig;
return ;
} const int MAXN = + ;
const int MAXBIGN = + ;
const int MAXL = + ;
const int INF = -1u >> ; struct Person
{
double x, y;
char Name[MAXL];
}P[MAXN]; int N, M, T; double Distance; int adj[MAXN][MAXN], Match[MAXN], L[MAXN];
int slack[MAXN]; bool vis[MAXN]; double Dist(Person a, Person b)
{
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
} bool Is_Cross(Person a, Person b, Person c)
{
if((a.x - b.x) * (b.y - c.y) == (b.x - c.x) * (a.y - b.y))
{
if(a.y == c.y) return (a.x < b.x && b.x < c.x) || (c.x < b.x && b.x < a.x);
else return (a.y < b.y && b.y < c.y) || (c.y < b.y && b.y < a.y);
} return false;
} void Try_Shot()
{
for(int i = ; i <= N; i++)
{
for(int j = M; j <= T; j++)
{
if(Dist(P[i], P[j]) > Distance) adj[i][j] = ;
else
{
int k;
for(k = ; k <= T; k++)
if(k != i && k != j && Is_Cross(P[i], P[k], P[j])) break; if(k > T) adj[i][j] = ;
else adj[i][j] = ;
}
}
} return ;
} int Scanname(char *S)
{
for(int i = ; i <= T; i++)
if(strcmp(P[i].Name, S) == ) return i; return -;
} void Format(char *S)
{
for(; *S; S++)
if(*S >= 'a' && *S <= 'z') *S = *S - 'a' + 'A'; return ;
} void KM_Init()
{
int p1, p2;
int v; char Name[MAXL]; scanf("%lf", &Distance);
Distance = Distance * Distance; read(N); M = N + ;
T = N + N; for(int i = ; i <= T; i++)
{
scanf("%lf%lf", &P[i].x, &P[i].y); scanf("%s", P[i].Name);
Format(P[i].Name);
} Try_Shot(); while(scanf("%s", Name) != EOF)
{
if(strcmp(Name, "End") == ) break;
Format(Name);
p1 = Scanname(Name); scanf("%s", Name);
Format(Name);
p2 = Scanname(Name); read(v); if(p1 > p2) swap(p1, p2); if(adj[p1][p2] != ) adj[p1][p2] = v;
} return ;
} bool Path(int i)
{ vis[i] = true; for(int j = M; j <= T; j++)
{
if(!vis[j] && adj[i][j] > )
{
int t = L[i] + L[j] - adj[i][j];
if(t == )
{
vis[j] = true;
if(Match[j] == || Path(Match[j]))
{
Match[j] = i;
return true;
}
}
else slack[j] = min(slack[j], t);
}
} return false;
} void KM_Solve()
{
int delta; for(int i = ; i <= N; i++)
for(int j = M; j <= T; j++)
L[i] = max(L[i], adj[i][j]); for(int i = ; i <= N; i++)
{
while()
{
memset(vis, , sizeof(vis));
for(int j = M; j <= T; j++) slack[j] = INF;
if(Path(i)) break; delta = INF; for(int k = M; k <= T; k++)
if(!vis[k] && slack[k] < delta)
delta = slack[k]; for(int j = ; j <= N; j++)
if(vis[j]) L[j] -= delta; for(int j = M; j <= T; j++)
if(vis[j]) L[j] += delta;
}
}
} void Print()
{
int Ans = ;
for(int i = M; i <= T; i++)
Ans += adj[Match[i]][i]; printf("%d\n", Ans); return ;
} int main()
{
KM_Init();
KM_Solve();
Print(); return ;
}

费用流的:

 #include<cstdio>
#include<iostream>
#include<cctype>
#include<queue>
#include<map>
#include<cstring>
#include<algorithm>
#define dist(i,j) (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])
using namespace std;
const int INF=;
const int maxn=;
const int maxm=;
struct Edge
{
int from,to,cap,flow,cost;
};
struct MCMF
{
int n,m;
int first[maxn],next[maxm];
Edge edges[maxm];
int d[maxn],p[maxn],a[maxn],inq[maxn];
void init(int n)
{
this->n=n;
m=;
memset(first,-,sizeof(first));
}
void AddEdge(int from,int to,int cap,int cost)
{
edges[m]=(Edge){from,to,cap,,cost};
next[m]=first[from];
first[from]=m++;
edges[m]=(Edge){to,from,,,-cost};
next[m]=first[to];
first[to]=m++;
}
int BellmanFord(int s,int t,int& flow,int& cost)
{
queue<int> Q;
memset(inq,,sizeof(inq));
for(int i=;i<=n;i++) d[i]=INF;
inq[s]=; d[s]=; a[s]=INF; Q.push(s);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
inq[x]=;
for(int i=first[x];i!=-;i=next[i])
{
Edge& e=edges[i];
if(e.cap>e.flow&&d[e.to]>d[x]+e.cost)
{
d[e.to]=d[x]+e.cost;
a[e.to]=min(a[x],e.cap-e.flow);
p[e.to]=i;
if(!inq[e.to])
{
inq[e.to]=;
Q.push(e.to);
}
}
}
}
if(d[t]==INF) return ;
flow+=a[t]; cost+=a[t]*d[t];
int x=t;
while(x!=s)
{
edges[p[x]].flow+=a[t];
edges[p[x]^].flow-=a[t];
x=edges[p[x]].from;
}
return ;
}
int solve(int s,int t)
{
int flow=,cost=;
while(BellmanFord(s,t,flow,cost));
return cost;
}
}sol;
double maxdist,x[maxn],y[maxn];
map<string,int> S;
int n,m,tot;
int id(string a)
{
int len=a.length();
for(int i=;i<len;i++) a[i]=tolower(a[i]);
if(!S.count(a))
{
S[a]=++tot;
return tot;
}
return S[a];
}
int can(int a,int c)
{
if((x[a]-x[c])*(x[a]-x[c])+(y[a]-y[c])*(y[a]-y[c])>maxdist*maxdist) return ;
for(int i=;i<=n*;i++) if(i!=a&&i!=c)
{
if((x[i]-x[a])*(x[i]-x[c])>) continue;
if((y[i]-y[a])*(y[i]-y[c])>) continue;
if((x[i]-x[a])*(y[c]-y[i])==(y[i]-y[a])*(x[c]-x[i])) return ;
}
return ;
}
int w[maxn][maxn];
int main()
{
scanf("%lf%d",&maxdist,&n);
sol.init(n*+);
double t1,t2;
for(int i=;i<=n;i++)
for(int j=n+;j<=n*;j++) w[i][j]=;
for(int i=;i<=n;i++)
{
string a;
scanf("%lf%lf",&t1,&t2);cin>>a;
int c=id(a);
x[i]=t1+;y[i]=t2+;
sol.AddEdge(n*+,i,,);
}
for(int i=;i<=n;i++)
{
string a;
scanf("%lf%lf",&t1,&t2);cin>>a;
int c=id(a);
x[i+n]=t1+;y[i+n]=t2+;
sol.AddEdge(i+n,*n+,,);
}
while()
{
string name;
cin>>name; if(name=="End") break;
int a,b,c;
a=id(name);
cin>>name;
b=id(name);
scanf("%d",&c);
if(a>b) swap(a,b);
w[a][b]=c;
}
for(int i=;i<=n;i++)
for(int j=n+;j<=n*;j++) if(can(i,j))
sol.AddEdge(i,j,,-w[i][j]);
printf("%d\n",-sol.solve(*n+,*n+));
return ;
}

COJ 3007 Mr.Yang的小助手的更多相关文章

  1. 发布代码小助手V2.1发布了——Code2HTML工具

    设计起源: 新浪博客似乎没有插入代码的功能,所以不得不用打空格的方法格式化代码.而且没法显示行号. 描述: 发布代码小助手用python和Tkinter开发,可以在任何常见操作系统上运行.主要用于在不 ...

  2. 书签小助手V1.1发布了

    更新信息: 1.修改了部分BUG;2.添加了一些不错的网站:3.重新设计了添加书签和编辑书签的界面. 安装说明: 类Ubuntu系统: 1.安装Python3解释器和Python3-tk sudo a ...

  3. 环境监测小助手V1.1的Windows版

    环境监测小助手V1.1——可以实时查看空气质量和城市排名 一款跨平台空气质量监测软件 数据来源互联网,请联网使用. 暂不支持效果预览. 下载地址:http://files.cnblogs.com/py ...

  4. Windows版词汇小助手V3.0发布了

    欢迎使用词汇小助手 作者:IT小小龙 电子邮箱:long_python@126.com 个人博客:http://blog.sina.com.cn/buduanqs 一款跨平台词汇查询记忆学习软件. 已 ...

  5. 词汇小助手V3.0发布了——不只是一个查单词的软件

    欢迎使用词汇小助手 作者:IT小小龙 电子邮箱:long_python@126.com 个人博客:http://blog.sina.com.cn/buduanqs 一款跨平台词汇查询记忆学习软件. 已 ...

  6. 生日小助手V4.0——迁移到Python3

    生日小助手V4.0——迁移到Python3 生日小助手V4.0只支持Linux系统,依赖命令行软件lunar Ubuntu系统安装方法:1.安装lunarsudo apt-get install lu ...

  7. DEDECMS-helper小助手扩展

    今天在做DEDE动态调用模板的时候卡住了,后终被强大的互联网解决,记录解决问题的过程,以备后用 可以在/data/helper.inc.php中进行默认小助手初始化的设置,系统默认载入小助手 例如创建 ...

  8. 【程序员小助手】Synergy,感受穿越屏幕之美

    内容简介 1.Synergy简介 2.Synergy安装与配置 3.附录 [程序员小助手]系列 在这个系列文章中(不定期更新),小编会把这些年(也没几年)的编程学习和工作中使用到的个人感觉非常好的软件 ...

  9. 【程序员小助手】Emacs,最强编辑器,没有之一

    内容简介 1.Emacs简介 2.Emacs三个平台的安装与配置 3.自动补全插件 4.小编的Emacs配置文件 5.常用快捷方式 6.和版本控制系统的配合(以SVN为例) [程序员小助手]系列 在这 ...

随机推荐

  1. PHP 中xampp不能启动服务器的问题

    有时候别人电脑上面的XAMPP,你把安装文件拷贝下来后,会发现,自己的电脑上用不了 这个时候有很多种情况 1. 关闭你自己电脑上有可能暂用80端口的程序 2.D:\xampp\apache\conf\ ...

  2. GridView 无数据时,绑定提示

    private void BindData() { DataTable dt = DAO.RunSQLReturnDt(this.getsql()); int dtcount = dt.Rows.Co ...

  3. JQ 日期格式化

    将字符转换为日期格式: function getDate(strDate) { var date = eval('new Date(' + strDate.replace(/\d+(?=-[^-]+$ ...

  4. 开发自己的cordova插件

    如果还没有配置过cordova环境,首先要下载nodejs,(下载地址https://nodejs.org/)下载完毕安装. 控制台: 1.输入npm -v 确定是否装上了 2.输入sudo npm ...

  5. jq 图片上传

    1.html <input type="file" class="ImgInput" name="ImgInput"/> 2.j ...

  6. ios开发之UIImageView

    废话少说,直接进入正题!!! 1.创建一个UIImageView: 创建一个UIImageView对象的几种方法: UIImageView *imageView1 = [[UIImageView al ...

  7. Mvvm绑定datagrid或listview的selectItems的方法[转]

    单选,很简单,将SelectedItem与ViewModel的属性进行双向绑定就OK了 多选,由于ListView的SelectedItems不能进行绑定,需要将ListView的SelectionC ...

  8. call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法.

    call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法. 注意:该函数的语法与 apply() 方法的语法几乎完全相同,唯一的区别在于,apply()方法接受的是一个参 ...

  9. <input>标签

    一. 上传图片: type="file":上传文件​ accept:选择上传的种类,图片或者是视频(/png只能上传png格式的图片) ​multiple="multip ...

  10. github的package.json内容

    补充:npm的init命令生成package.json Name 必须字段. 小提示: 不要在name中包含js, node字样: 这个名字最终会是URL的一部分,命令行的参数,目录名,所以不能以点号 ...