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的:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 using namespace std;
  6
  7 void read(int& x)
  8 {
  9     x = 0;
 10     int sig = 1;
 11     char ch = getchar();
 12
 13     while(!isdigit(ch))
 14     {
 15         if(ch == ‘-‘) sig = -1;
 16         ch = getchar();
 17     }
 18
 19     while(isdigit(ch))
 20     {
 21         x = 10 * x + ch - ‘0‘;
 22         ch = getchar();
 23     }
 24
 25     x *= sig;
 26     return ;
 27 }
 28
 29 const int MAXN = 60 + 5;
 30 const int MAXBIGN = 40 + 5;
 31 const int MAXL = 200 + 10;
 32 const int INF = -1u >> 1;
 33
 34 struct Person
 35 {
 36     double x, y;
 37     char Name[MAXL];
 38 }P[MAXN];
 39
 40 int N, M, T;
 41
 42 double Distance;
 43
 44 int adj[MAXN][MAXN], Match[MAXN], L[MAXN];
 45 int slack[MAXN];
 46
 47 bool vis[MAXN];
 48
 49 double Dist(Person a, Person b)
 50 {
 51     return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
 52 }
 53
 54 bool Is_Cross(Person a, Person b, Person c)
 55 {
 56     if((a.x - b.x) * (b.y - c.y) == (b.x - c.x) * (a.y - b.y))
 57     {
 58         if(a.y == c.y) return (a.x < b.x && b.x < c.x) || (c.x < b.x && b.x < a.x);
 59         else return (a.y < b.y && b.y < c.y) || (c.y < b.y && b.y < a.y);
 60     }
 61
 62     return false;
 63 }
 64
 65 void Try_Shot()
 66 {
 67     for(int i = 1; i <= N; i++)
 68     {
 69           for(int j = M; j <= T; j++)
 70           {
 71                if(Dist(P[i], P[j]) > Distance) adj[i][j] = 0;
 72             else
 73             {
 74                 int k;
 75                 for(k = 1; k <= T; k++)
 76                     if(k != i && k != j && Is_Cross(P[i], P[k], P[j])) break;
 77
 78                    if(k > T) adj[i][j] = 1;
 79                    else adj[i][j] = 0;
 80               }
 81         }
 82     }
 83
 84     return ;
 85 }
 86
 87 int Scanname(char *S)
 88 {
 89     for(int i = 1; i <= T; i++)
 90       if(strcmp(P[i].Name, S) == 0) return i;
 91
 92     return -1;
 93 }
 94
 95 void Format(char *S)
 96 {
 97     for(; *S; S++)
 98       if(*S >= ‘a‘ && *S <= ‘z‘) *S = *S - ‘a‘ + ‘A‘;
 99
100     return ;
101 }
102
103 void KM_Init()
104 {
105     int p1, p2;
106     int v;
107
108     char Name[MAXL];
109
110     scanf("%lf", &Distance);
111     Distance = Distance * Distance;
112
113     read(N);
114
115     M = N + 1;
116     T = N + N;
117
118     for(int i = 1; i <= T; i++)
119     {
120         scanf("%lf%lf", &P[i].x, &P[i].y);
121
122         scanf("%s", P[i].Name);
123         Format(P[i].Name);
124     }
125
126     Try_Shot();
127
128     while(scanf("%s", Name) != EOF)
129     {
130         if(strcmp(Name, "End") == 0) break;
131         Format(Name);
132         p1 = Scanname(Name);
133
134         scanf("%s", Name);
135         Format(Name);
136         p2 = Scanname(Name);
137
138         read(v);
139
140         if(p1 > p2) swap(p1, p2);
141
142         if(adj[p1][p2] != 0) adj[p1][p2] = v;
143     }
144
145     return ;
146 }
147
148 bool Path(int i)
149 {
150
151     vis[i] = true;
152
153     for(int j = M; j <= T; j++)
154     {
155         if(!vis[j] && adj[i][j] > 0)
156         {
157             int t = L[i] + L[j] - adj[i][j];
158             if(t == 0)
159             {
160                 vis[j] = true;
161                 if(Match[j] == 0 || Path(Match[j]))
162                 {
163                     Match[j] = i;
164                     return true;
165                 }
166             }
167             else slack[j] = min(slack[j], t);
168         }
169     }
170
171     return false;
172 }
173
174 void KM_Solve()
175 {
176     int delta;
177
178     for(int i = 1; i <= N; i++)
179       for(int j = M; j <= T; j++)
180         L[i] = max(L[i], adj[i][j]);
181
182     for(int i = 1; i <= N; i++)
183     {
184         while(1)
185         {
186             memset(vis, 0, sizeof(vis));
187             for(int j = M; j <= T; j++) slack[j] = INF;
188             if(Path(i)) break;
189
190             delta = INF;
191
192             for(int k = M; k <= T; k++)
193               if(!vis[k] && slack[k] < delta)
194                 delta = slack[k];
195
196             for(int j = 1; j <= N; j++)
197               if(vis[j]) L[j] -= delta;
198
199             for(int j = M; j <= T; j++)
200               if(vis[j]) L[j] += delta;
201         }
202     }
203 }
204
205 void Print()
206 {
207     int Ans = 0;
208     for(int i = M; i <= T; i++)
209       Ans += adj[Match[i]][i];
210
211     printf("%d\n", Ans);
212
213     return ;
214 }
215
216 int main()
217 {
218     KM_Init();
219     KM_Solve();
220     Print();
221
222     return 0;
223 }

费用流的:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cctype>
  4 #include<queue>
  5 #include<map>
  6 #include<cstring>
  7 #include<algorithm>
  8 #define dist(i,j) (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])
  9 using namespace std;
 10 const int INF=2000000000;
 11 const int maxn=110;
 12 const int maxm=80010;
 13 struct Edge
 14 {
 15     int from,to,cap,flow,cost;
 16 };
 17 struct MCMF
 18 {
 19     int n,m;
 20     int first[maxn],next[maxm];
 21     Edge edges[maxm];
 22     int d[maxn],p[maxn],a[maxn],inq[maxn];
 23     void init(int n)
 24     {
 25         this->n=n;
 26         m=0;
 27         memset(first,-1,sizeof(first));
 28     }
 29     void AddEdge(int from,int to,int cap,int cost)
 30     {
 31         edges[m]=(Edge){from,to,cap,0,cost};
 32         next[m]=first[from];
 33         first[from]=m++;
 34         edges[m]=(Edge){to,from,0,0,-cost};
 35         next[m]=first[to];
 36         first[to]=m++;
 37     }
 38     int BellmanFord(int s,int t,int& flow,int& cost)
 39     {
 40         queue<int> Q;
 41         memset(inq,0,sizeof(inq));
 42         for(int i=1;i<=n;i++) d[i]=INF;
 43         inq[s]=1; d[s]=0; a[s]=INF; Q.push(s);
 44         while(!Q.empty())
 45         {
 46             int x=Q.front(); Q.pop();
 47             inq[x]=0;
 48             for(int i=first[x];i!=-1;i=next[i])
 49             {
 50                 Edge& e=edges[i];
 51                 if(e.cap>e.flow&&d[e.to]>d[x]+e.cost)
 52                 {
 53                     d[e.to]=d[x]+e.cost;
 54                     a[e.to]=min(a[x],e.cap-e.flow);
 55                     p[e.to]=i;
 56                     if(!inq[e.to])
 57                     {
 58                         inq[e.to]=1;
 59                         Q.push(e.to);
 60                     }
 61                 }
 62             }
 63         }
 64         if(d[t]==INF) return 0;
 65         flow+=a[t]; cost+=a[t]*d[t];
 66         int x=t;
 67         while(x!=s)
 68         {
 69             edges[p[x]].flow+=a[t];
 70             edges[p[x]^1].flow-=a[t];
 71             x=edges[p[x]].from;
 72         }
 73         return 1;
 74     }
 75     int solve(int s,int t)
 76     {
 77         int flow=0,cost=0;
 78         while(BellmanFord(s,t,flow,cost));
 79         return cost;
 80     }
 81 }sol;
 82 double maxdist,x[maxn],y[maxn];
 83 map<string,int> S;
 84 int n,m,tot;
 85 int id(string a)
 86 {
 87     int len=a.length();
 88     for(int i=0;i<len;i++) a[i]=tolower(a[i]);
 89     if(!S.count(a))
 90     {
 91         S[a]=++tot;
 92         return tot;
 93     }
 94     return S[a];
 95 }
 96 int can(int a,int c)
 97 {
 98     if((x[a]-x[c])*(x[a]-x[c])+(y[a]-y[c])*(y[a]-y[c])>maxdist*maxdist) return 0;
 99     for(int i=1;i<=n*2;i++) if(i!=a&&i!=c)
100     {
101         if((x[i]-x[a])*(x[i]-x[c])>0) continue;
102         if((y[i]-y[a])*(y[i]-y[c])>0) continue;
103         if((x[i]-x[a])*(y[c]-y[i])==(y[i]-y[a])*(x[c]-x[i])) return 0;
104     }
105     return 1;
106 }
107 int w[maxn][maxn];
108 int main()
109 {
110     scanf("%lf%d",&maxdist,&n);
111     sol.init(n*2+2);
112     double t1,t2;
113     for(int i=1;i<=n;i++)
114        for(int j=n+1;j<=n*2;j++) w[i][j]=1;
115     for(int i=1;i<=n;i++)
116     {
117         string a;
118         scanf("%lf%lf",&t1,&t2);cin>>a;
119         int c=id(a);
120         x[i]=t1+50;y[i]=t2+50;
121         sol.AddEdge(n*2+1,i,1,0);
122     }
123     for(int i=1;i<=n;i++)
124     {
125         string a;
126         scanf("%lf%lf",&t1,&t2);cin>>a;
127         int c=id(a);
128         x[i+n]=t1+50;y[i+n]=t2+50;
129         sol.AddEdge(i+n,2*n+2,1,0);
130     }
131     while(1)
132     {
133         string name;
134         cin>>name; if(name=="End") break;
135         int a,b,c;
136         a=id(name);
137         cin>>name;
138         b=id(name);
139         scanf("%d",&c);
140         if(a>b) swap(a,b);
141         w[a][b]=c;
142     }
143     for(int i=1;i<=n;i++)
144        for(int j=n+1;j<=n*2;j++) if(can(i,j))
145         sol.AddEdge(i,j,1,-w[i][j]);
146     printf("%d\n",-sol.solve(2*n+1,2*n+2));
147     return 0;
148 }
时间: 2024-10-18 06:34:13

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

微信企业号企业小助手有什么用?

企业小助手是企业号下默认添加的应用,它用来向用户发送企业号的系统消息,如: a)成员关注:向微信侧推送关注成功通知,或身份验证提示语.(成员如何关注企业号?) b)二次验证:向微信侧推送二次验证提示语,提示用户回复验证信息:(二次验证的作用和流程?) c)用户状态变更:向企业应用转发用户关注/退出通知,实时监测全局用户关注情况:(用户状态变更通知有什么用?) d)分级管理员:向微信侧推送相关提示,协助分级管理员设置/重置密码.(什么是分级管理员?如何创建?设置时有哪些限制?) 注: 1)  企业

大三上学期安卓一边学一边开始做一个自己觉得可以的项目 广商小助手App 加油

这项目构思好多 一个人一步一步来 一边做一边为后面应用铺设 广商小助手APP 设计出的软件登录场景 实现(算是可以) 界面大体出来了 界面点击方面也做了很多特效 上图其实点击各颜色后会出现各种图和反应 当然还有好多东西没弄 当前时代都看脸一个不精美的软件少人用 所以多花心思 项目还在努力中>>>>>>>

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

 内容简介 1.Synergy简介 2.Synergy安装与配置 3.附录 [程序员小助手]系列 在这个系列文章中(不定期更新),小编会把这些年(也没几年)的编程学习和工作中使用到的个人感觉非常好的软件推荐给大家,希望能够共享美好资源,使大家提高编程和办事效率. Synergy,感受穿越屏幕之美 什么?你面前有多个电脑屏幕,而你每个屏幕(或每台电脑)单独配一个鼠标和一个键盘? 什么?你在多个屏幕之间复制黏贴东西的时候还需要借助samba这样的共享软件? 什么?你只有一台电脑,只有一个屏幕?好吧

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

内容简介 1.Emacs简介 2.Emacs三个平台的安装与配置 3.自动补全插件 4.小编的Emacs配置文件 5.常用快捷方式 6.和版本控制系统的配合(以SVN为例) [程序员小助手]系列 在这个系列文章中(不定期更新),小编会把这些年(也没几年)的编程学习和工作中使用到的个人感觉非常好的软件推荐给大家,希望能够共享美好资源,使大家提高编程和办事效率. Emacs,最强编辑器,没有之一 小编知道,此标题一出,肯定会遭受广大群众“诟病”,说不好还会被其他编辑器的粉丝暗地里“干掉”. 比如,V

网络小助手项目开发总结报告

网络小助手项目开发总结报告 1引言 1.1编写目的 通过一段时间后对网络小助手项目进行详细开发和测试,该项目已经基本完成.本报告旨在将项目开发过程中的经验和不足之处进行总结,为以后的团队开发活动积累经验.本报告经审核后,交由软件工程老师王老师审查. 1.2背景 说明: a.  软件项目名称:网络小助手 b.  开发者:兰梦,李金吉,马翔,赵天,胡佳奇 用户:学生 系统运行环境:windows XP/windows 7/windows 8下的通用PC 1.3参考资料 <软件工程--原理,方法与应用

Visual_Assist_X破解方法(vs小助手破解方法)

1.下载vs小助手破解版(360网盘下载): 网盘地址:http://yunpan.cn/cHTe2fYCihWEx  访问密码: 82ef 2.全盘搜索:“VA_X.dll” 3.将路径下“C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\12.0\Extensions\hcg4gpeo.dh0”(ps:不同电脑可能路径不同)的“VA_X.dll”替换为破解版中的“VA_X.dll”.下图为破解版vs小助手的文件: 4.破解

Windows Phone中悬浮小助手的制作过程

前言      看到过其他平台游戏中第三方sdk的一些悬浮的小助手,近来无聊,就做个玩儿,看着比较简单,做起来还是花费了不少力气. 开始 首先是页面的xaml代码,其实比较简单,就是一些Canvas里面装了些image和一个border(是作为按钮展开后的背景).下面注释的那个canvas是为了看到悬浮窗在界面右边的时的效果,方便做动画添加的,读者不用在意 要求悬浮按钮可以拖动,拖动后靠在自动屏幕边上显示,拖动的时候超过屏幕的中轴就靠在右边,点击按钮向左边以此展开按钮,如果拖动后在屏幕中轴左边则

练手小项目(2)-生活小助手--周公解梦

第一篇 练手小项目(2)-生活小助手--身份证查询 第二篇 练手小项目(2)-生活小助手--星座运势查询 我在想就是第三个药品查询要不要写出来,因为布局还在讨论用什么展示,因为药品有很多展示,我也不知道用什么展示. 这是一个很纠结的事情 我就先写第四个吧 周公解梦 其中代码有点错误我想用for循环进行判断返回数据有几个 但是总是失败,如果有看本篇贴子,解决了,给我留个言,在这篇帖子我只显示一个结果 布局跟简单的说 一个Edittext 获取数据,然后button进行数据提取发送到服务器 返回的数

双色球小助手

500w.py from pyCyp import * from tkinter import * from tkinter import ttk #from tkinter import messagebox import itertools urlNewqi = 'http://kaijiang.500.com/' newqi = getNewqi(urlNewqi) url = 'http://datachart.500.com/ssq/history/newinc/history.php