COJ 3007 Mr.Yang的小助手
传送门: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的小助手的更多相关文章
- 发布代码小助手V2.1发布了——Code2HTML工具
设计起源: 新浪博客似乎没有插入代码的功能,所以不得不用打空格的方法格式化代码.而且没法显示行号. 描述: 发布代码小助手用python和Tkinter开发,可以在任何常见操作系统上运行.主要用于在不 ...
- 书签小助手V1.1发布了
更新信息: 1.修改了部分BUG;2.添加了一些不错的网站:3.重新设计了添加书签和编辑书签的界面. 安装说明: 类Ubuntu系统: 1.安装Python3解释器和Python3-tk sudo a ...
- 环境监测小助手V1.1的Windows版
环境监测小助手V1.1——可以实时查看空气质量和城市排名 一款跨平台空气质量监测软件 数据来源互联网,请联网使用. 暂不支持效果预览. 下载地址:http://files.cnblogs.com/py ...
- Windows版词汇小助手V3.0发布了
欢迎使用词汇小助手 作者:IT小小龙 电子邮箱:long_python@126.com 个人博客:http://blog.sina.com.cn/buduanqs 一款跨平台词汇查询记忆学习软件. 已 ...
- 词汇小助手V3.0发布了——不只是一个查单词的软件
欢迎使用词汇小助手 作者:IT小小龙 电子邮箱:long_python@126.com 个人博客:http://blog.sina.com.cn/buduanqs 一款跨平台词汇查询记忆学习软件. 已 ...
- 生日小助手V4.0——迁移到Python3
生日小助手V4.0——迁移到Python3 生日小助手V4.0只支持Linux系统,依赖命令行软件lunar Ubuntu系统安装方法:1.安装lunarsudo apt-get install lu ...
- DEDECMS-helper小助手扩展
今天在做DEDE动态调用模板的时候卡住了,后终被强大的互联网解决,记录解决问题的过程,以备后用 可以在/data/helper.inc.php中进行默认小助手初始化的设置,系统默认载入小助手 例如创建 ...
- 【程序员小助手】Synergy,感受穿越屏幕之美
内容简介 1.Synergy简介 2.Synergy安装与配置 3.附录 [程序员小助手]系列 在这个系列文章中(不定期更新),小编会把这些年(也没几年)的编程学习和工作中使用到的个人感觉非常好的软件 ...
- 【程序员小助手】Emacs,最强编辑器,没有之一
内容简介 1.Emacs简介 2.Emacs三个平台的安装与配置 3.自动补全插件 4.小编的Emacs配置文件 5.常用快捷方式 6.和版本控制系统的配合(以SVN为例) [程序员小助手]系列 在这 ...
随机推荐
- Java的演变过程
1. 1996.01.23 JDK1.0 代号Oak:212个类.8个包: 2. 1997.02.19 JDK1.1 504个类.23个包: Java Bean.远程方法调用(RMI).JAR文件格式 ...
- SQL Server 2008 安装指南
一.安装需求: 1.硬件需求条件 硬件 需求 处理器 最低:1.4 GHz(x64处理器)注意:Windows Server 2008 for Itanium-Based Systems 版本需要In ...
- LINUX启动顺序
Linux 启动顺序: 1. BIOS自检 (服务器硬件启动的第一步,坑定的啦) 2. 运行系统内核并检测硬件(这个是看系统了,redhat等相关版本是通过/boot/vm进行启动 vmlinuz) ...
- HDU 4296 Buildings(贪心)
题意: 给定n个建筑物,每个建筑物都有两个属性w, s,每个建筑物都有一个PDV = (Σw j)-s i .意思就是它上面的所有的w相加减去它的s,让求怎么放置这个建筑物使得每个建筑物当中PDV最大 ...
- enter 默认搜索
onkeydown=" if(event.keyCode==13) Search(); "
- sublime的js调试环境(基于node环境)
很多的语言都有控制台,都要专门的ide,js,用sublime在node的环境下,可以配置console, 如何配置?首先,要有node的环境,下载安装,还要安装到c盘才行,然后找到'工具(tool) ...
- 彻底删除mysql的方法(有隐藏文件)
1.建议使用360进行卸载,可以彻底卸载软件 2.360会提醒删除注册表 3.这个隐藏文件要删除掉 在 C:\Documents and Settings\ 路径下搜索 MySQL 文件夹(默认隐藏的 ...
- Java 最简单的批处理
批处理Batch && PreparedStatement : import java.sql.*; public class TestBatch { public static vo ...
- Android 开发笔记——通过 Intent 传递类对象
Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...
- C#开发基于Http的LaTeX数学公式转换器
本文将讲解如何通过codecogs.com和Google.com提供的API接口来将LaTeX数学函数表达式转化为图片形式.具体思路如下: (1)通过TextBox获取用户输入的LaTeX数学表达式, ...