第一题
题目大意
给出一个参考点,再给出 n n n个点,求这 n n n个点中距参考点欧几里得最近的 3 3 3个点的编号。如果距离相同,则按照编号升序排序。
解法
直接求出每个点距离参考点的距离,再排序即可。
如果不会排序,则扫三遍距离,每次找不同并且最小的即可。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=2005;
int x,n,y;
struct node
{
int id;
double dis;
} pos[maxn];
double get(double x,double y,double xx,double yy)
{
return (x-xx)*(x-xx)+(y-yy)*(y-yy);
}
bool cmp(node a,node b) {return a.dis==b.dis?a.id<b.id:a.dis<b.dis;}
int main()
{
scanf("%d%d%d",&n,&x,&y);
for(int i=1,tx,ty;i<=n;i++)
{
scanf("%d%d",&tx,&ty);
pos[i].id=i;
pos[i].dis=get(tx,ty,x,y);
}
sort(pos+1,pos+n,cmp);
for(int i=1;i<=3;i++) printf("%d\n",pos[i].id);
return 0;
}
第二题
题目大意
给出一个疫区,再给出
n
n
n个人各
t
t
t个时刻的行踪。如果某人某时刻在疫区内,则算经过;如果某人连续
t
t
t时刻都在疫区内,则算停留。求这
n
n
n个人中经过和停留疫区的各多少人。
解法
直接模拟即可,注意要连续 t t t时刻才算停留。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,k,t,xl,yd,xr,yu,x,y;
bool check()
{
if(x>=xl&&x<=xr&&y>=yd&&y<=yu) return true;
return false;
}
int main()
{
scanf("%d%d%d%d%d%d%d",&n,&k,&t,&xl,&yd,&xr,&yu);
int ans1=0,ans2=0;
for(int i=1;i<=n;i++)
{
int temp=0,t2=0;
bool flag=false;
for(int j=1;j<=t;j++)
{
scanf("%d%d",&x,&y);
if(check())
{
temp++;
t2++;
if(t2>=k) flag=true;
}
else t2=0;
}
if(temp) ans1++;
if(flag) ans2++;
}
printf("%d\n%d",ans1,ans2);
return 0;
}
第三题
题目大意
给出许多逻辑器件,告诉每一个逻辑器件的输入,再给出外输入,求给定器件最后的输出。只考虑时序电路,即如果产生了循环,则输出"LOOP"。
题解
一眼看过去就是拓扑排序,先跑一遍求出拓扑序,然后就可以直接根据拓扑序进行处理。正好拓扑排序也可以判环,跑完拓扑排序后看是否还有点有入度,如果有,即有环。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<string>
#include<vector>
using namespace std;
const int maxn=10005;
map<string,int> mp;
int T,type[maxn],in[maxn],que[maxn],head[maxn];
int sta[maxn],cnt=0,s,n,m,degree[maxn];
struct node
{
int to,next;
} edge[maxn<<1];
inline void add(int u,int v)
{
edge[++cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
void clear()
{
memset(type,0,sizeof(type));
memset(head,0,sizeof(head));
memset(degree,0,sizeof(degree));
memset(sta,0,sizeof(sta));
cnt=0;
}
inline int getnum(string str)
{
int x=0,len=str.length()-1;
for(int i=1;i<=len;i++) x=(x<<1)+(x<<3)+str[i]-48;
return x;
}
int main()
{
#ifdef lemon
freopen("C.txt","r",stdin);
#endif
mp["NOT"]=1;mp["AND"]=2;mp["OR"]=3;
mp["XOR"]=4;mp["NAND"]=5;mp["NOR"]=6;
scanf("%d",&T);
while(T--)
{
clear();
scanf("%d%d",&m,&n);
for(int i=1,k;i<=n;i++)
{
string opt,str;
cin>>opt;
type[i]=mp[opt];
// printf("%d\n",type[i]);
scanf("%d",&k);
while(k--)
{
cin>>str;
// cout<<str<<endl;
int id=getnum(str);
// printf("%d\n",id);
if(str[0]=='I')
{
add(id+n,i);
degree[i]++;
}
else
{
add(id,i);
degree[i]++;
}
}
}
// printf("%d %d\n",m,n);
scanf("%d",&s);
vector<int> in[maxn],que[maxn];
for(int i=1,x;i<=s;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&x);
in[i].push_back(x);
}
}
for(int i=1,x,ss;i<=s;i++)
{
scanf("%d",&ss);
while(ss--)
{
scanf("%d",&x);
que[i].push_back(x);
}
}
queue<int> q;
vector<int> vec[maxn],ord;
bool loop=false;
for(int i=1;i<=n+m;i++)
{
if(!degree[i])
{
q.push(i);
}
}
while(!q.empty())
{
int x=q.front();q.pop();
ord.push_back(x);
for(int i=head[x];i;i=edge[i].next)
{
if(!(--degree[edge[i].to]))
{
q.push(edge[i].to);
}
vec[edge[i].to].push_back(x);
}
}
for(int i=1;i<=n+m;i++) if(degree[i]) loop=true;
if(loop) printf("LOOP\n");
else
{
// printf("%d\n",ord.size());
// for(int i=0;i<ord.size();i++) printf("%d ",ord[i]);printf("\n");
for(int t=1;t<=s;t++)
{
for(int i=1;i<=m;i++) sta[i+n]=in[t][i-1];
// for(int i=0;i<(int)ord.size();i++) printf("#%d %d\n",ord[i],vec[ord[i]].size());
for(int i=0;i<(int)ord.size();i++)
{
if(ord[i]>n) continue;
if(type[ord[i]]==1)
{
sta[ord[i]]=!sta[vec[ord[i]][0]];
}
else if(type[ord[i]]==2)
{
sta[ord[i]]=sta[vec[ord[i]][0]];
for(int j=1;j<vec[ord[i]].size();j++)
{
sta[ord[i]]&=sta[vec[ord[i]][j]];
}
}
else if(type[ord[i]]==3)
{
sta[ord[i]]=sta[vec[ord[i]][0]];
for(int j=1;j<vec[ord[i]].size();j++)
{
sta[ord[i]]|=sta[vec[ord[i]][j]];
}
}
else if(type[ord[i]]==4)
{
sta[ord[i]]=sta[vec[ord[i]][0]];
for(int j=1;j<vec[ord[i]].size();j++)
{
sta[ord[i]]^=sta[vec[ord[i]][j]];
}
}
else if(type[ord[i]]==5)
{
sta[ord[i]]=sta[vec[ord[i]][0]];
for(int j=1;j<vec[ord[i]].size();j++)
{
sta[ord[i]]&=sta[vec[ord[i]][j]];
}
sta[ord[i]]=!sta[ord[i]];
}
else if(type[ord[i]]==6)
{
sta[ord[i]]=sta[vec[ord[i]][0]];
for(int j=1;j<vec[ord[i]].size();j++)
{
sta[ord[i]]|=sta[vec[ord[i]][j]];
}
sta[ord[i]]=!sta[ord[i]];
}
}
for(int i=0;i<que[t].size();i++) printf("%d ",sta[que[t][i]]);
printf("\n");
}
}
}
return 0;
}
第四题(仅作参考)
题目大意
给出
n
n
n个点,再给出一个半径为
r
r
r的圆/球/超球体(这里记为CIRCLE)。对于每个点,需要求出这个点与其他点的最短距离之和,不能经过CIRCLE。
解法
对于两个点连线不经过CIRCLE的一对点,最近距离就是直接连线。
对于两个点连线经过CIRCLE的一对点,最近距离就是切线+圆弧+切线。
但是这道题调了3个小时也不对,不知道是写挂了还是思路有问题。
最后只过了40分的所有点都在圆上的情况。
代码(40分)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double pi=acos(-1.0);
const int maxn=105;
int n,m,r,c[maxn],p[2005][maxn];
inline double getdis(int x,int y)
{
return 0;
}
void work15()
{
for(int i=1;i<=m;i++)
{
double temp=0;
for(int j=1;j<=m;j++)
{
if(i==j) continue;
double dis=sqrt((double)(p[i][1]-p[j][1])*(p[i][1]-p[j][1])+(double)(p[i][2]-p[j][2])*(p[i][2]-p[j][2]));
double tdis=dis/2.0;
double sinv=tdis/(double)r;
// printf("@%lf\n",sinv);
double ta=asin(sinv)*2;
// printf("#%lf\n",ta/pi);
temp+=ta*r;
}
printf("%.14lf\n",temp);
}
}
int main()
{
#ifdef lemon
freopen("D.txt","r",stdin);
#endif
scanf("%d%d%d",&n,&m,&r);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) scanf("%d",&p[i][j]);
if(m<=50) work15();
else
{
for(int i=1;i<=m;i++)
{
double temp=0;
for(int j=1;j<=m;j++)
{
if(i==j) continue;
double tt=0;
for(int k=1;k<=n;k++) tt+=(double)(p[i][k]-p[j][k])*(p[i][k]-p[j][k]);
double dis=sqrt(tt);
double tdis=dis/2.0;
double sinv=tdis/(double)r;
// printf("@%lf\n",sinv);
double ta=asin(sinv)*2;
// printf("#%lf\n",ta/pi);
temp+=ta*r;
}
printf("%.14lf\n",temp);
}
}
return 0;
}
628

被折叠的 条评论
为什么被折叠?



