您的位置:首页 > 其它

【URAL 刷题记】URAL 1600 ~ URAL 1607

2016-02-09 14:47 489 查看
URAL 1600

/*
题意: 给三维空间中n个点, 且每个点有平均飞行的向量. 问是否存在一个时间, 2个东西距离<=d

暴力枚举点对, 然后三分判最低点是不是小于等于d.如果是的话, 在其左侧二分寻找恰好距离为d的时间.
(我是直接取一个平面以后看成射线与圆的交点问题。。。)
*/
#include<cstdio>
#include<cmath>

double eps=1e-8;

int dcmp(const double& x){ return fabs(x)<eps ? 0 : (x<0 ? -1 : 1); }

struct Point3{
double x,y,z;
Point3(){}
Point3(double x,double y,double z):x(x),y(y),z(z){}
bool operator ==(const Point3& B)const{ return dcmp(x-B.x)==0 && dcmp(y-B.y)==0 && dcmp(z-B.z)==0; }
void read(){
double x,y,z; scanf("%lf%lf%lf",&x,&y,&z);
this->x=x, this->y=y, this->z=z;
}
};
Point3 operator +(const Point3& A,const Point3& B){ return Point3(A.x+B.x,A.y+B.y,A.z+B.z); }
Point3 operator -(const Point3& A,const Point3& B){ return Point3(A.x-B.x,A.y-B.y,A.z-B.z); }
Point3 operator *(const Point3& A,const double& b){ return Point3(A.x*b,A.y*b,A.z*b); }
Point3 operator /(const Point3& A,const double& b){ return Point3(A.x/b,A.y/b,A.z/b); }
double Dot(const Point3& A,const Point3& B){ return A.x*B.x+A.y*B.y+A.z*B.z; }
double Length(const Point3& A){ return sqrt(Dot(A,A)); }
Point3 Cross(const Point3& A,const Point3& B){ return Point3(A.y*B.z-A.z*B.y, A.z*B.x-A.x*B.z, A.x*B.y-A.y*B.x); }

double DistanceToLine(const Point3& P, const Point3& A,const Point3& B){
Point3 v1=B-A, v2=P-A;
return Length(Cross(v1,v2))/Length(v1);
}
double DistanceToSegment(const Point3& P, const Point3& A,const Point3& B){
if(A==B) return Length(P-A);
Point3 v1=B-A, v2=P-A, v3=P-B;
if(dcmp(Dot(v1,v2))<0) return Length(v2);
else if(dcmp(Dot(v1,v3))>0) return Length(v3);
else return Length(Cross(v1,v2))/Length(v1);
}
double DistanceToHalfline(const Point3& P, const Point3& A,const Point3& B){
if(A==B) return Length(P-A);
Point3 v1=B-A, v2=P-A;
if(dcmp(Dot(v1,v2))<0) return Length(v2);
else return Length(Cross(v1,v2))/Length(v1);
}

const int maxn=510;

int n; double D;

Point3 A[maxn],v[maxn];

double mit; int mix,miy;

double sqr(double x){ return x*x; }
void calc(){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j)if(j!=i){
if(Length(A[j]-A[i])<D){ mit=0,mix=i,miy=j; return; }
double x=DistanceToHalfline(A[i],A[j],A[j]+(v[j]-v[i]));
if(dcmp(x-D)<=0){
double d1=sqrt(sqr(Length(A[j]-A[i]))-sqr(x)), d2=sqrt(sqr(D)-sqr(x));
double t=fabs((d2-d1)/Length(v[j]-v[i]));

if(dcmp(t-mit)<0){
mit=t; mix=i, miy=j;
}
}
}
}
}

void solve(){
scanf("%d%lf",&n,&D);
for(int i=1;i<=n;++i){
A[i].read(); v[i].read();
}

mit=1e30; mix=-1;
calc();

if(mix==-1) puts("OK");
else printf("ALARM!\n%.3lf %d %d\n",mit,mix,miy);
}

int main(){
//  freopen("in.txt","r",stdin);
solve();
//  for(;;);
return 0;
}


URAL 1601

/*
简单模拟题,将非句子开头的大写字母转化成小写即可,注意行首字母不一定大写
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cctype>

const int maxn=10010;

int n;
char s[maxn];
void solve(){
int fst=1;
while (gets(s)){
n=strlen(s);
for(int i=0;i<n;++i){
if(isalpha(s[i])){
if(fst){
putchar(toupper(s[i]));
fst=0;
}else putchar(tolower(s[i]));
}else putchar(s[i]);
if(s[i]=='.' || s[i]=='!' || s[i]=='?') fst=1;
}
putchar('\n');
}
}
int main(){
//  freopen("in.txt","r",stdin);
solve();
//  for(;;);
return 0;
}


URAL 1602

/*
C题:一个人坐电梯,一开始电梯在k层,电梯要先下到1层,人可以从n层先下到x层再叫电梯。。。

枚举人先走到哪层即可。。。

(注意,人按电梯,电梯才会上楼。。)
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

const double eps=1e-8;

double dcmp(double x){ return fabs(x)<eps ? 0 : (x < 0 ? -1 : 1); }

int n,k; double u,v;
void solve(){
scanf("%d%d%lf%lf",&n,&k,&u,&v);

double mit=(n-1)*u; int mix=1;
for(int x=n;x>=2;--x){
double t1=(n-x)*u, t2=(k-1)*v+15;
double tm=max(t1,t2)+(x-1)*v+5+(x-1)*v;
if(dcmp(tm-mit)<0){ mit=tm; mix=x; }
}
printf("%d\n",mix);
}
int main(){
//  freopen("in.txt","r",stdin);
solve();
//  for(;;);
return 0;
}


URAL 1603

/*
题意:给4*4的填字格,组成单词的方法是:从一个格子开始向四周走,然后不能走到同一个格子,给m个单词问能否用这个方法组成。
题解:直接把所有可能的单词全做出来,判断即可
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;

const int maxn=10;

string res[100000]; int resN;

const int dxy[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

char mp[maxn][maxn];

bool check(int x,int y){ return 0<=x&&x<4&&0<=y&&y<4; }

bool vis[maxn][maxn];
void dfs(int x,int y,string now){
vis[x][y]=1;
res[resN++]=now;
for(int d=0;d<4;++d){
int X=x+dxy[d][0], Y=y+dxy[d][1];
if(check(X,Y)&&!vis[X][Y]){
dfs(X,Y,now+mp[X][Y]);
}
}
vis[x][y]=0;
}

char now[maxn*maxn];
void solve(){
for(int i=0;i<4;++i)
scanf("%s",mp[i]);

memset(vis,0,sizeof vis);
for(int i=0;i<4;++i)
for(int j=0;j<4;++j)
dfs(i,j,string("") + mp[i][j]);

sort(res,res+resN);
int m;scanf("%d",&m);
while(m--){
scanf("%s",now); string nows=now;
printf("%s: ",now);
//      cout << *lower_bound(res,res+resN,nows) << endl;
if(nows==*lower_bound(res,res+resN,nows)) puts("YES"); else puts("NO");
}

}
int main(){
//  freopen("in.txt","r",stdin);
solve();
//  for(;;);
return 0;
}


URAL 1604

/*
是给你n个数,有k种。要求把它们排成一列,使得相邻两个相同的情况尽可能少。

把出现次数最多的和次多的依次放就行了,搞个堆。
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;

typedef pair<int,int> P;

priority_queue<P> pq;

int k;
void solve(){
scanf("%d",&k);
for(int i=1;i<=k;++i){
int x;scanf("%d",&x);
pq.push(P(x,i));
}

while(!pq.empty()){
P x=pq.top(); pq.pop();
if(pq.empty()){
for(int i=0;i<x.first;++i)
printf("%d ",x.second);
break;
}
P y=pq.top(); pq.pop();
printf("%d %d ",x.second,y.second);
if(x.first>1) pq.push(P(x.first-1,x.second));
if(y.first>1) pq.push(P(y.first-1,y.second));
}
putchar('\n');
}
int main(){
//  freopen("in.txt","r",stdin);
solve();
//  for(;;);
return 0;
}


URAL 1605

/*
数列是逼近2/3的数列,所以xn是 k/2^n (0<=k<=2^n)里面最接近2/3的,然后奇数项小于2/3,偶数项大于2/3
通项公式 floor((2^i) * 2 / 3) + (i%2) 暴力求出这个数即可

c++的做法的话,通项公式
x_n = 2/3 + (1/3)/(2^(n-1)) n is odd
x_n = 2/3 - (1/3)/(2^(n-1)) n is even
观察后面一部分,设d=(1/3)/(2^(n-1))=0.00..0XXX..XX
可以知道,小数点后0的个数是k=floor[Log10(3)+(n-1)*Log10(2)]
那么,
如果n is odd,如果d>0.00..0333..3(0的个数=k),那么答案输出k-1,否则输出k
如果n is even,如果d>0.00..0666..6(0的个数=k),那么答案输出k-1,否则输出k
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;

typedef long double LD;

int n;

void solve(){
scanf("%d",&n);
//  if(n==100000) { puts("30102"); return; }
LD t=log10(3)+(n-1)*log10(2);
int k=(int)t;
LD lgD=-t,lgA=(n&1) ? (-log10(3)-k) : (log10(2)-log10(3)-k);

//  cout << k << ' ' << (double)pow(10,lgA) << ' ' << (double)pow(10,lgD) << ' ' << (lgA>lgD) << endl;
//  printf("%d %d\n",pow(10,lgA)<=pow(10,lgD), lgA<=lgD);

printf("%d\n",k-(lgA<=lgD));
}
int main(){
//  freopen("in.txt","r",stdin);

/*  double a=0,b=1,c;
for(int t=0;t<10;++t){
c=(a+b)/2;
printf("%d %.10lf\n",t+2,c);
a=b;b=c;
}
*/  solve();
//  for(;;);
return 0;
}


URAL 1606

/*
滑雪,从上到下,然后轨迹要是折线,拐点必须在桩上,而且每次都得转向(一次往左一次往右),然后最大化碰到的桩数

直接维护<x,>x数的最大值即可。
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<functional>
using namespace std;

typedef pair<int,int> P;

const int maxn=100010;

int upd(int& a,int b){ return a<b ? a=b,1 : 0; }

int Tl[maxn],Tr[maxn],TN;
int Til[maxn], Tir[maxn];
void add(int* T,int* Ti,int x,int v,int i){ for(;x<=TN;x+=x&-x) if(upd(T[x],v)) Ti[x]=i; }
P sum(int* T,int* Ti,int x){ int v=-1,vi; for(;x;x-=x&-x) if(upd(v,T[x])) vi=Ti[x]; return P(v,vi); }

int g[maxn][2];

pair<P,int> a[maxn];

int n;

void print(int i,int j){
if(g[i][j]) print(g[i][j],j^1);
printf("%d ",a[i].second);
}

void solve(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
int x,y;scanf("%d%d",&x,&y);
a[i]=make_pair(P(y,x),i);
}
sort(a+1,a+1+n,greater< pair<P,int> >());

TN=100000;
memset(Tl,0,sizeof Tl);
memset(Tr,0,sizeof Tr);
memset(Til,0,sizeof Til);
memset(Tir,0,sizeof Tir);
int res=-1; P resi;
for(int i=1;i<=n;++i){
int x=a[i].first.second, fl,fr;
P p;
p=sum(Tr,Tir,TN-(x+1)+1); fl=p.first+1, g[i][0]=p.second;
p=sum(Tl,Til,x-1); fr=p.first+1, g[i][1]=p.second;
//      printf("%d %d\n",fl,fr);
add(Tl,Til,x,fl,i); add(Tr,Tir,TN-x+1,fr,i);
if(upd(res,fl)) resi=P(i,0);
if(upd(res,fr)) resi=P(i,1);
}
printf("%d\n",res);
print(resi.first, resi.second); putchar('\n');
}
int main(){
//  freopen("in.txt","r",stdin);

solve();

//  for(;;);
return 0;
}


URAL 1607

/*
题意: 乘客坐计程车, 乘客一开始出价a, 司机要价c, 两人没达成一致的话 乘客加b, 司机减d 问什么时候两人成交
模拟即可
注意特判
1. 如果一开始出价就满足,直接输出
2. 如果某次乘客加价超过司机价格,此时乘客直接按司机价格输出
3. 如果某次司机减价低于乘客价格,此时司机直接按乘客价格输出
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

int a,b,c,d;
void solve(){
scanf("%d%d%d%d",&a,&b,&c,&d);
for(;a<c;){
if(a+b>=c){ a=c; break; }
a+=b;
if(c-d<=a)break;
c-=d;
}
printf("%d\n",a);
}
int main(){
//  freopen("in.txt","r",stdin);
solve();
//  for(;;);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm URAL