这套题目比较简单,为了庆祝为数不多的AK,决定把题解发一下。233....
A. Smooth Visualization(UVALive 5870 Smooth Visualization)
签到题一个,搞搞搞就行了。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 10000;
char ans[10][maxn];
char ch[maxn];
void solve()
{
int len = strlen(ch);
int cnt = ch[0] - '0';
cnt = 7 - cnt;
int q = ch[0] - '0';
for(int i = 0; i < 7; i ++)
{
if(cnt)
{
ans[i][0] = '*'; cnt --;
}
else ans[i][0] = '+';
}
int n = 1;
for(int i = 1; i < len; i ++)
{
q = max(q, ch[i] - '0');
int tmp = ch[i] - ch[i - 1];
if(abs(tmp) <= 1)
{
cnt = 7 - (ch[i] - '0');
for(int j = 0; j < 7; j ++)
{
if(cnt)
{
ans[j][n] = '*'; cnt --;
}
else ans[j][n] = '+';
}
n ++;
}
else if(tmp > 0)
{
ch[i - 1] ++;
cnt = 7 - (ch[i - 1] - '0');
for(int j = 0; j < 7; j ++)
{
if(cnt)
{
ans[j][n] = '*'; cnt --;
}
else ans[j][n] = '+';
}
n ++; i --;
}
else
{
ch[i - 1] --;
cnt = 7 - (ch[i - 1] - '0');
for(int j = 0; j < 7; j ++)
{
if(cnt)
{
ans[j][n] = '*'; cnt --;
}
else ans[j][n] = '+';
}
n ++; i --;
}
}
for(int i = 0; i < 7; i ++)
ans[i][n] = 0;
for(int i = 7 - q; i < 7; i ++)
puts(ans[i]);
}
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
scanf("%s", ch);
solve();
}
return 0;
}
B. Arnooks's Defensive Line(UVALive 5871 Arnooks's Defensive Line )
因为看起来是单组数据,n=500000,cdq分治的话,算了下时间复杂度正好。于是就是一道cdq分治裸题。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 500100;
struct Node
{
char op;
int l, r, id;
void in(int i)
{
char ch[2];
scanf("%s%d%d", ch, &l, &r);
op = ch[0]; id = i;
}
bool operator < (const Node& rhs) const
{
return l < rhs.l;
}
}a[maxn];
int C[maxn];
void add(int x, int ad)
{
while(x < maxn)
{
C[x] += ad;
x += x & (-x);
}
}
int sum(int x)
{
int ret = 0;
while(x)
{
ret += C[x];
x -= x & (-x);
}
return ret;
}
int n;
vector<int> vec;
int ans[maxn];
void divide(int l, int r)
{
if(l == r) return ;
int m = (l + r) >> 1;
divide(l, m);
divide(m + 1, r);
sort(a + l, a + m + 1);
sort(a + m + 1, a + r + 1);
int cnt = 0;
for(int i = m + 1, j = l; i <= r; i ++)
{
while(j <= m && a[j].l <= a[i].l)
{
if(a[j].op != '?') add(a[j].r, 1), cnt ++;
j ++;
}
if(a[i].op == '?')
{
if(ans[a[i].id] == -1) ans[a[i].id] = 0;
ans[a[i].id] += cnt - sum(a[i].r - 1);
}
}
for(int i = m + 1, j = l; i <= r; i ++)
{
while(j <= m && a[j].l <= a[i].l)
{
if(a[j].op != '?') add(a[j].r, -1);
j ++;
}
}
}
void solve()
{
vec.clear();
for(int i = 1; i <= n; i ++)
{
vec.push_back(a[i].r);
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
for(int i = 1; i <= n; i ++)
{
a[i].r = lower_bound(vec.begin(), vec.end(), a[i].r) - vec.begin() + 1;
}
CLR(C, 0);
CLR(ans, -1);
divide(1, n);
for(int i = 1; i <= n; i ++)
if(ans[i] != -1) printf("%d\n", ans[i]);
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
a[i].in(i);
solve();
return 0;
}
C. Equivalence(UVALive 5872 Equivalence )
这题随便模拟就好了。做的时候uvalive崩掉了,于是连交了十来发。。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 1200000000000000000ll
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
map<string,LL> mp;
map<string,LL> ::iterator it;
struct Exp{
vector<string> _exp;
vector<LL> xishu;
char tmp[100];
void init(){
_exp.clear();
xishu.clear();
}
void hebing(){
mp.clear();
for(int i=0;i<_exp.size();i++){
sort(_exp[i].begin(),_exp[i].end());
mp[_exp[i]]+=xishu[i];
}
init();
for(it=mp.begin();it!=mp.end();++it){
if(it->yy!=0) _exp.push_back(it->xx),xishu.push_back(it->yy);
}
}
};
Exp add(Exp a,Exp b){
Exp ans;ans=b;
for(int i=0;i<a._exp.size();i++){
ans._exp.push_back(a._exp[i]);
ans.xishu.push_back(a.xishu[i]);
}
ans.hebing();
return ans;
}
Exp sub(Exp a,Exp b){
Exp ans;ans=a;
for(int i=0;i<b._exp.size();i++){
ans._exp.push_back(b._exp[i]);
ans.xishu.push_back(-b.xishu[i]);
}
ans.hebing();
return ans;
}
Exp mult(Exp a,Exp b){
Exp ans;ans.init();
for(int i=0;i<a._exp.size();i++){
for(int j=0;j<b._exp.size();j++){
string tmp=a._exp[i];
if(tmp == "1") tmp = b._exp[j];
else if(b._exp[j] != "1") tmp=tmp+b._exp[j];
ans._exp.push_back(tmp);
ans.xishu.push_back(a.xishu[i]*b.xishu[j]);
}
}
ans.hebing();
return ans;
}
string a, b;
Exp dfs(int l, int r)
{
Exp ret; ret.init();
if(l == r)
{
if(a[l] >= '0' && a[l] <= '9')
{
ret._exp.push_back("1");
ret.xishu.push_back(a[l] - '0');
}
else
{
string str = "";
str += a[l];
ret._exp.push_back(str);
ret.xishu.push_back(1);
}
return ret;
}
vector<Exp> vec;
string str = "";
for(int i = l; i <= r; i ++)
{
Exp tmp;
if(a[i] == '(')
{
int j = i + 1, cnt = 1;
while(j <= r)
{
if(a[j] == '(') cnt ++;
else if(a[j] == ')') cnt --;
if(cnt == 0) break;
j ++;
}
tmp = dfs(i + 1, j - 1);
i = j;
}
else
{
tmp = dfs(i, i);
}
i ++;
if(i <= r) str += a[i];
vec.push_back(tmp);
}
Exp tmp; tmp.init();
for(int i = 0; i < vec.size(); i ++)
{
tmp = vec[i];
int j = i;
while(i < str.size() && str[i] == '*')
{
tmp = mult(tmp, vec[i + 1]);
i ++;
}
if(j)
{
if(str[j - 1] == '+') ret = add(ret, tmp);
else
{
ret = sub(ret, tmp);
}
}
else ret = tmp;
}
return ret;
}
char ch1[10010], ch2[10010];
void solve()
{
gets(ch1);
gets(ch2);
int len = strlen(ch1);
a = "(";
for(int i = 0; i < len; i ++)
{
if(ch1[i] == ' ' || ch1[i] == '\t') continue;
a += ch1[i];
}
a += ")";
b = "";
int len2 = strlen(ch2);
for(int i = 0; i < len2; i ++)
{
if(ch2[i] == ' ' || ch2[i] == '\t') continue;
b += ch2[i];
}
a += "-(";
a += b;
a += ")";
for(int i = 0; i < a.size(); i ++)
{
if(a[i] >= 'A' && a[i] <= 'Z')
{
a[i] = a[i] - 'A' + 'a';
}
}
Exp ret = dfs(0, a.size() - 1);
if(ret._exp.size() == 0) puts("YES");
else puts("NO");
}
int main(){
int T;
scanf("%d", &T);
getchar();
while(T --)
{
solve();
}
return 0;
}
D. Tree Inspections (UVALive 5873 Tree Inspections )
这题题意是给你n个点,然后m个横线或者竖线,如果满足在直线上站着,能垂直看到60%以上的点的话,就输出PASSED。
横线和竖线情况相同,对于一个横线,只需要考虑他和相邻横线之间的看见的情况就可以了。可以分向上看和向下看两种情况。然后模拟一下就行了。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 100100;
struct Point
{
int x, y, id;
void inpt(int i)
{
scanf("%d%d", &x, &y);
id = i;
}
}p[maxn];
bool cmp1(Point a, Point b)
{
return a.x < b.x;
}
bool cmp2(Point a, Point b)
{
return a.y < b.y;
}
vector<int> H, V;
bool vis[maxn];
void solve()
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++)
p[i].inpt(i);
H.clear(); V.clear();
for(int i = 0; i < m; i ++)
{
char op[2]; int x;
scanf("%s%d", op, &x);
if(op[0] == 'H') H.push_back(x);
else V.push_back(x);
}
CLR(vis, false);
sort(H.begin(), H.end());
sort(V.begin(), V.end());
sort(p, p + n, cmp1);
map<int, int> mp;
for(int i = 0, j = 0; i < H.size(); i ++)
{
int h = H[i];
mp.clear();
while(j < n && p[j].x <= h)
{
if(mp.count(p[j].y))
{
if(p[mp[p[j].y]].x > p[j].x)
{
mp[p[j].y] = j;
}
}
else mp[p[j].y] = j;
j ++;
}
map<int, int>::iterator it;
for(it = mp.begin(); it != mp.end(); it ++)
{
vis[p[it->yy].id] = true;
}
}
for(int i = 0, j = n - 1; i < H.size(); i ++)
{
int h = H[i];
mp.clear();
while(j >= 0 && p[j].x >= h)
{
if(mp.count(p[j].y))
{
if(p[mp[p[j].y]].x < p[j].x)
{
mp[p[j].y] = j;
}
}
else mp[p[j].y] = j;
j --;
}
map<int, int>::iterator it;
for(it = mp.begin(); it != mp.end(); it ++)
{
vis[p[it->yy].id] = true;
}
}
sort(p, p + n, cmp2);
for(int i = 0, j = 0; i < V.size(); i ++)
{
int v = V[i];
mp.clear();
while(j < n && p[j].y <= v)
{
if(mp.count(p[j].x))
{
if(p[mp[p[j].y]].y > p[j].y)
{
mp[p[j].x] = j;
}
}
else mp[p[j].x] = j;
j ++;
}
map<int, int>::iterator it;
for(it = mp.begin(); it != mp.end(); it ++)
{
vis[p[it->yy].id] = true;
}
}
for(int i = 0, j = n - 1; i < V.size(); i ++)
{
int v = V[i];
mp.clear();
while(j >= 0 && p[j].y >= v)
{
if(mp.count(p[j].x))
{
if(p[mp[p[j].y]].y < p[j].y)
{
mp[p[j].x] = j;
}
}
else mp[p[j].x] = j;
j --;
}
map<int, int>::iterator it;
for(it = mp.begin(); it != mp.end(); it ++)
{
vis[p[it->yy].id] = true;
}
}
int ans = 0;
for(int i = 0; i < n; i ++)
if(vis[i]) ans ++;//, printf("%d -- %d\n", p[i].x, p[i].y);
if(ans * 10 >= n * 6) puts("PASSED");
else puts("FAILED");
}
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
solve();
}
return 0;
}
E. Social Holidaying(UVALive 5874 Social Holidaying)
这题直接最大匹配就过了。可以的就连双向边,然后最大匹配除以二
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn=1000;
int a[maxn],b[maxn];
struct BPM
{
int n, m; // 左右顶点个数
vector<int> G[maxn]; // 邻接表
int left[maxn]; // left[i]为右边第i个点的匹配点编号,-1表示不存在
bool T[maxn]; // T[i]为右边第i个点是否已标记
void init(int n, int m) {
this->n = n;
this->m = m;
for(int i=0;i<=n;i++) G[i].clear();
}
bool match(int u){
for(int i = 0;i < G[u].size(); i++) {
int v=G[u][i];
if(!T[v]) {
T[v] = true;
if (left[v] == -1 || match(left[v])){
left[v] = u;
return true;
}
}
}
return false;
}
// 求最大匹配
int solve() {
memset(left, -1, sizeof(left));
int ans = 0;
for(int u = 0; u < n; u++) {
memset(T, 0, sizeof(T));
if(match(u)) ans++;
}
return ans;
}
}sol;
set<int> _hash;
int main(){
int t;scanf("%d",&t);
while(t--){
int n,m;scanf("%d%d",&n,&m);
_hash.clear();
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<m;i++){
scanf("%d",&b[i]);
_hash.insert(b[i]);
}
sol.init(n,n);
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++) if(i!=j){
if(_hash.find(a[i]+a[j])!=_hash.end()){
sol.G[i].push_back(j);
sol.G[j].push_back(i);
}
}
}
printf("%d\n",sol.solve()/2);
}
return 0;
}
F. Orienteering(UVALive 5875 Orienteering)
这题发现不能背包距离,但是可以背包分数呀!于是愉快的背包出所有分数的最短距离。然后每个询问查一下就行了。查的时候随便查,二分什么的都行。暴力也能过。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 60600;
#define MOD 1000000009
double eps = 1e-8;
double dp[33][maxn];
double sqr(double x){
return x*x;
}
int sign(double x){
return (x>eps)-(x<-eps);
}
struct Point
{
double x, y;
int s;
void inpt()
{
scanf("%lf%lf%d", &x, &y, &s);
}
}p[40];
double dist(Point a,Point b){
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
int Max[40];
double dis[40][40];
double ans[maxn];
int n;
void solve()
{
for(int i = 1; i <= n; i ++)
p[i].inpt();
p[0].x = 0; p[0].y = 0; p[0].s = 0;
for(int i = 0; i <= n; i ++)
{
for(int j = 0; j <= n; j ++)
dis[i][j] = dist(p[i], p[j]);
}
for(int i = 0; i <= n; i ++)
{
for(int j = 0; j < maxn; j ++)
dp[i][j] = 1e30;
}
dp[0][0] = 0;
Max[0] = 0;
for(int i = 1; i <= n; i ++)
{
Max[i] = 0;
for(int j = 0; j < i; j ++)
{
for(int k = 0; k <= Max[j]; k ++)
{
dp[i][k + p[i].s] = min(dp[i][k + p[i].s], dp[j][k] + dis[i][j] - dis[j][0] + dis[i][0]);
}
Max[i] = max(Max[i], Max[j] + p[i].s);
}
}
for(int i = 0; i < maxn; i ++)
ans[i] = 1e20;
int tot = 0;
for(int i = 0; i <= n; i ++)
{
tot = max(tot, Max[i]);
for(int j = 0; j <= Max[i]; j ++)
{
ans[j] = min(ans[j], dp[i][j]);
}
}
char ch[100]; double d;
while(scanf("%s%lf", ch, &d), ch[0] != '#')
{
int out = -1;
for(int i = 0; i <= tot; i ++)
{
if(sign(d - ans[i]) >= 0)
{
out = i;
}
}
printf("%s: %d\n", ch, out);
}
}
int main()
{
int T, cas = 1;
while(scanf("%d", &n), n)
{
printf("Race %d\n", cas ++);
solve();
}
}
G. Writings on the Wall(UVALive 5876 Writings on the Wall)
求两个串可重叠的相连有多少种情况,扩展kmp裸题。。当s后缀和t公共前缀等于s后缀长度的时候,就是可以拼接的时候。然后。。ans++
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 1200000000000000000ll
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 100100;
#define MOD 1000000007
const int N = 101010;
int next[N],extand[N];
void getnext(char *T) // next[i]: 以第i位置开始的子串 与 T的公共前缀
{
int i,length = strlen(T);
next[0] = length;
for(i = 0; i<length-1 && T[i]==T[i+1]; i++);
next[1] = i;
int a = 1;
for(int k = 2; k < length; k++)
{
int p = a+next[a]-1, L = next[k-a];
if( (k-1)+L >= p )
{
int j = (p-k+1)>0? (p-k+1) : 0;
while(k+j<length && T[k+j]==T[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较
next[k] = j, a = k;
}
else next[k] = L;
}
}
void getextand(char *S,char *T)
{
memset(next,0,sizeof(next));
getnext(T);
int Slen = strlen(S), Tlen = strlen(T), a = 0;
int MinLen = Slen>Tlen?Tlen:Slen;
while(a<MinLen && S[a]==T[a]) a++;
extand[0] = a, a = 0;
for(int k = 1; k < Slen; k++)
{
int p = a+extand[a]-1, L = next[k-a];
if( (k-1)+L >= p )
{
int j = (p-k+1)>0? (p-k+1) : 0;
while(k+j<Slen && j<Tlen && S[k+j]==T[j] ) j++;
extand[k] = j;
a = k;
}
else extand[k] = L;
}
}
char s[N],t[N];
void solve()
{
scanf("%s%s",s,t);
getextand(s,t);
int ans = 1;
int len = strlen(s);
for(int i = 0; i < len; i++)
{
if(len - i == extand[i]) ans ++;
}
printf("%d\n", ans);
}
int main()
{
int T;
scanf("%d", &T);
while(T --) solve();
return 0;
}
H. Robotic Traceur(UVALive 5877 Robotic Traceur)
就是最小步数的最短路,并没有发现什么坑。。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const double eps=1e-8;
double sqr(double x)
{
return x*x;
}
int sign(double x)
{
return (x>eps)-(x<-eps);
}
const int maxn = 1010;
struct Point
{
double x,y;
Point(double _x=0,double _y=0)
{
x=_x,y=_y;
}
void input()
{
scanf("%lf%lf",&x,&y);
}
} p[1024];
double dist(Point a,Point b){
return sqr(a.x-b.x)+sqr(a.y-b.y);
}
vector<int> G[maxn];
bool vis[maxn];
int dp[maxn];
int gao(int s, int t)
{
queue<int> Q;
Q.push(s);
CLR(vis, false);
CLR(dp, INF);
dp[s] = 0;
while(!Q.empty())
{
int u = Q.front(); Q.pop();
vis[u] = false;
for(int i = 0; i < G[u].size(); i ++)
{
int v = G[u][i];
if(dp[v] > dp[u] + 1)
{
dp[v] = dp[u] + 1;
if(!vis[v]) Q.push(v);
vis[v] = true;
}
}
}
return dp[t];
}
void solve()
{
int n, s, t;
double l1, l2;
scanf("%d%d%d%lf%lf", &n, &s, &t, &l1, &l2);
l1 += l2;
for(int i = 1; i <= n; i ++)
p[i].input(), G[i].clear();
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= n; j ++) if(i != j)
{
if(sign(dist(p[i], p[j]) - sqr(l1)) <= 0)
{
G[i].push_back(j);
}
}
}
int ret = gao(s, t);
if(ret == INF) puts("Impossible");
else printf("%d\n", ret);
}
I. Shortest Leash(UVALive 5878 Shortest Leash)
其实我发这篇文的目的,就是说一下这道题。。
这道题上来就被秒了,然而我感觉这道题很神啊!赛后发现大家都是用黑科技过的。。怪不得过了那么多。。个人感觉我们的思路是“杠杠的”正确。
最后的答案,肯定是2^n种情况求出的点后排的凸包上的点。然后,假如我们已经用了前i个向量,而且求出了相应的凸包,那么,考虑第i+1个向量对当前的凸包的影响,就是把当前凸包向着i+1这个向量的两个方向拉伸了一些长度,稍微想象一下可以知道,这样的拉伸最多增加两个点啊!!于是,每次增加向量最多增加两个点。。于是,按顺序添加向量,维护凸包就可以了。。。
加向量,排凸包,加向量,排凸包。。复杂度O(n^2*log(n))。
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const double inf=1e10;
const double eps=1e-8;
double sqr(double x){
return x*x;
}
int sign(double x){
return (x>eps)-(x<-eps);
}
struct Point{
double x,y;
Point(double _x=0,double _y=0){
x=_x,y=_y;
}
Point operator+(const Point &a){
return Point(x+a.x,y+a.y);
}
Point operator-(const Point &a){
return Point(x-a.x,y-a.y);
}
void input(){
scanf("%lf%lf",&x,&y);
}
}p[1024],v[1024],res[1024];
double mult(Point sp,Point ep,Point op){
return (sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y);
}
bool operator<(const Point &l,const Point &r){
return l.y<r.y||(l.y==r.y&&l.x<r.x);
}
int graham(Point pnt[],int n,Point res[]){
int i,len,k=0,top=1;
sort(pnt,pnt+n);
if(n==0) return 0;res[0]=pnt[0];
if(n==1) return 1;res[1]=pnt[1];
if(n==2) return 2;res[2]=pnt[2];
for(i=2;i<n;i++){
while(top&&mult(pnt[i],res[top],res[top-1])>=0) top--;
res[++top]=pnt[i];
}
len=top;res[++top]=pnt[n-2];
for(i=n-3;i>=0;i--){
while(top!=len&&mult(pnt[i],res[top],res[top-1])>=0) top--;
res[++top]=pnt[i];
}
return top;
}
double dist(Point a,Point b){
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
int main(){
int n;
while(scanf("%d",&n),n){
p[0]=Point(0,0);
int m=1;
double ans=-inf;
for(int i=0;i<n;i++){
Point tp;tp.input();
int l=0;
for(int j=0;j<m;j++){
p[m+l]=p[j]+tp;l++;
p[m+l]=p[j]-tp;l++;
}
m=graham(p,m+l,res);
for(int j=0;j<m;j++) p[j]=res[j];
for(int j=0;j<m;j++) ans=max(ans,dist(res[j],Point(0,0)));
}
printf("%.3f\n",ans);
}
return 0;
}