现场其实想到了找两点间最大边,但是一直在想DFS找的方法,期间我也想了想预处理的可行性,可是想岔道了,觉得不可行,结果今天用类似DP的预处理终于给过了,我擦了,铁牌第一名,要多点背有多点背。莫非是RP用光了,希望明年能好点吧。
Run ID
Problem ID
Status
Time
Memory
Language
Code
Submit At
User
这道题的解法其实有两种,另一种是先求一棵最小生成树,然后枚举每一条最小生成树上的边,拆掉后变成两个生成树,然后找两个集合中点权最大的两个连接起来,这是暴力贪心策略。而正解是北大教练讲的,先求一棵最小生成树,通过类似DP的预处理将每两点之间的最大边求出来,然后,一个二重循环枚举每对点,减掉最大边,添上点权就行。
/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define LOCA
#define MAXN 10005
#define INF 100000000
#define eps 1e-11
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
double d[1005][1005]; //存储两点间距离
double dis[1005];
bool used[1005];
int n;
double mx[1005][1005];
int near[1005]; //记录每次所加的边,如果near[i] = -1 就说明顶点i已经加到生成树中了。
struct point
{
double x, y;
int po;
} p[1005];
double distan(point x, point y)
{
return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
}
int main()
{
#ifdef LOCAL
freopen("d:/data.in","r",stdin);
freopen("d:/data.out","w",stdout);
#endif
int T, i, j, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(i = 1; i <= n; i++)
scanf("%lf%lf%d", &p[i].x, &p[i].y, &p[i].po);
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
d[i][j] = d[j][i] = distan(p[i], p[j]);
mx[i][j] = 0;
}
}
memset(used, false, sizeof(used));
for(i = 1; i <= n; i++)
{
dis[i] = d[1][i];
near[i] = 1;
}
used[1] = true;
double B = 0;
int A;
near[1] = -1;
for(i = 1; i < n; i++)
{
int mi = INF;
int v = -1;
for(j = 1; j <= n; j++)
{
if(near[j] != -1 && dis[j] < mi)
{
v = j;
mi = dis[j];
}
}
int pre;
if(v != -1)
{
pre = near[v];
B += d[v][near[v]];
//printf("%d %d ddd\n", near[v], v);
mx[near[v]][v] = mx[v][near[v]] = d[v][near[v]]; //邻接的点之间的最大边是自己
near[v] = -1;
for(j = 1; j <= n; j++)
{
if(near[j] != -1 && d[v][j] < dis[j])
{
dis[j] = d[v][j];
near[j] = v;
}
}
}
for(j = 1; j <= n; j++)
{
if(near[j] == -1 && j != v)
{
mx[j][v] = mx[v][j] = max(mx[j][pre], mx[pre][v]); //转移方程,代表j到v的最大边为j到pre和pre到v的最大边中的大的。
}
}
}
double ans = 0;
for(i = 1; i <= n; i++) //二重循环遍历
{
for(j = 1; j <= n; j++)
{
if(i == j) continue;
A = p[i].po + p[j].po;
if((double)A / (B - mx[i][j]) > ans)
ans = (double)A / (B - mx[i][j]);
}
}
printf("%.2f\n", ans);
}
return 0;
}
分享到:
相关推荐
ACM/ICPC参赛者必备!模版库,数十页的C++代码,涵盖ACM/ICPC中出现的各种算法!此为吉林大学版,内容相对比较全,排版质量是各校的模板中最好的!
acm/icpc 课件 贪心 递归 图论 最大矩阵乘积 acm/icpc 课件 贪心 递归 图论 最大矩阵乘积 acm/icpc 课件 贪心 递归 图论 最大矩阵乘积 acm/icpc 课件 贪心 递归 图论 最大矩阵乘积 acm/icpc 课件 贪心 递归 图论 ...
ACM/ICPC大赛
The 36th ACM/ICPC Asia Regional Shanghai Site —— Online Contest Problem Set
ACM/ICPC中国*辽宁第二届大学生程序设计竞赛题目
ACM/ICPC亚洲预赛成都赛区网络赛真题,分享给广大热衷于ACM的人们们!
acm/icpc算法集合。acm/icpc算法集合。acm/icpc算法集合。
搜索
2010年ACM/ICPC珠海区域赛决赛题目
ACM/ICPC World Finals 1990 task
PKU 、POJ ACM/ICPC300多题的代码,还有各种典型问题的分类代码
有关于2011华中南赛区ACM/ICPC程序设计邀请赛及“永新视博”杯程序设计大赛的解题报告,希望对名位有所帮助!!!!!
近几年负责命题的赛区有:2008年北京赛区,2009年宁波赛区,2010年杭州赛区,2010年福州赛区,2011年北京赛区,2011年福州赛区,2012年金华赛区,2012年杭州赛区。2013年杭州赛区。均由此课程主讲教师郭炜负责命题。...
ACM/ICPC的教学与实践
浙江师范大学 ACM/ICPC 集训队――算法设计入门学习资料浙江师范大学 ACM/ICPC 集训队――算法设计入门学习资料
ACM/icpc的练习题目分类,非常全面的关于poj题目的分类
收录了92年至08年ACM全球总决赛(World Finals)的试题(PDF) 03年至08年题解正制作中 将会很快上传 请拭目以待
果子合并(ACM/ICPC训练题): 有四堆果子, 其数量分别是:10, 30, 15和100,试设计一种最佳方案,将果子合并为一堆,使得合并工作量最小。 注:规定合并两堆果子的工作量是这两堆果子的数量之和。 哈夫曼树及其应用...
吉林大学计算机科学学院2005年制作的ACMICPC代码库