0821上午有感而发
T1 Circle
给出N个圆,保证任意两个圆都是相离的,然后给出两个点(x1,y1)(x2,y2)保证均不在某个圆上,要从点(x1,y1)到(x2,y2)画条曲线,问这条曲线最少要跨越多少次圆的边界?对于100%的数据:1<=N<=50,坐标范围[-1000,1000],每个圆的半径1<=R<=1000。
保证没有两个圆有公共点,起点和终点不会落到某个圆的边界上。
考场上想到了直接数两个点一共被几个圆包起来就是答案了。
判断一个点在不在圆内,只用看这个点到圆心的距离是否小于R就可以了,判断的时候得开double,不然见祖宗。。。
直接枚举圆+判断=\(AC\)
还要考虑到重复的情况,但是我没有想到。。。题目太美丽了,喜提\(90pts\)
复杂度\(O(n)\)
$90pts$ $code$
#define rgi register int
#define ll long long
#define ull unsigned long long
#define N 55
using namespace std;
struct cir{
int x,y,r;
}e[N];
inline int contains(int x,int y,cir z){
long double del=sqrt((x-z.x)*(x-z.x)+(y-z.y)*(y-z.y));
return del<z.r;
}
int n,x,y,x2,y2,ans=0;
int main(){
freopen("circle.in","r",stdin);
freopen("circle.out","w",stdout);
cin.tie(0)->ios::sync_with_stdio(false);
cin>>n;
for(rgi i=1;i<=n;i++) cin>>e[i].x;
for(rgi i=1;i<=n;i++) cin>>e[i].y;
for(rgi i=1;i<=n;i++) cin>>e[i].r;
cin>>x>>y>>x2>>y2;
for(rgi i=1;i<=n;i++){
ans+=contains(x,y,e[i])+contains(x2,y2,e[i]);
}
printf("%d",ans);
return 0;
}
T2 Ski
【题目描述】
建造滑雪场的升降轨道。起点和终点的高度已知,x坐标分割成若干份,间隔为1,每一点都给出支架的高度。要选择尽可能少的支架顶端建立固定点,两个固定点之间用一条直钢轨连接,要求中间支架的高度都不能超过钢轨在那里的高度。而且两个相邻固定点之间的距离(x坐标的差值)不能超过给定的K。
【输入格式】
第一行是N和K,2≤N≤5000;1≤K≤N-1;
接下来N行,按顺序给定支架的高度h,0≤h≤1000000000;
【输出格式】
一个整数,表示最少要选择几个固定点。第一个(起点)和最后一个(终点)一定是固定点。
简单来说就是在点上架桥,桥的数量要最少。
考虑钢轨的斜率,如果两根柱子之间的柱子都小于钢轨的当点高度就进行转移。设计状态就也很简单。。
\(dp[i]\)表示到第i个点的最小固定点数,枚举区间\([j,i]\),如果满足条件,转移\(dp[i]=min(dp[j]+1)\)
我也是比较无奈,考场上算的复杂度感觉起来过不了这题,想了一下优化大概30min,之后就放弃了,这种解法都没打。。悲提\(0pts\)
复杂度不会算(真的太蒻了。。。
T3 Patric
有N个人,每个人有一个身高,他们排成一条直线,求有多少对人能够互相看到对方。看到对方的条件为:两个人相邻或两个人之间不存在任何人比他们高。
大水,单调栈板子题。
看完发现就是单调栈,因为当前比当前点高度小的都没用,维护单调递减的序列就可以了。
ans加的时候教练用了二分优化。。,感觉作用不大。
当其他人在美美地写暴力时,我不知为何和高度相同的杠上了,。,。白费(蒻爆了。。
T4 Cdrom
题面太长,简单来说就是一群\(OIer\)拷文件,u可以拷给v,求\(CCF\)最少要发几个u盘
写的时候想到了是有向边,但是脑筋急转弯觉得没大影响,数连通块去了。。。用的并查集。其实思路一样,就是数有几块。
班里一位神犇用了Tarjan??感觉不是很必要。
教练还说考虑环,有Floyd又删边的。。
直接BFS不就好了吗,加一个vis就可以处理环了。
神犇code
using namespace std;
const int maxn = 205;
const int maxm = 40005;
inline int read(){
int ret=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f*=-1;ch=getchar();}
while(isdigit(ch)) ret=(ret<<3)+(ret<<1)+(ch&15),ch=getchar();
return ret*f;
}
int a[maxn][maxn];
int r[maxn][maxn];
bool visited[maxn];
stack<int> st;
bool has_edge[maxn][maxn];
int n,cnt,in_degree[maxn],comp[maxn];
void dfs1(int u) {
visited[u] = true;
for (int i=1;i<=a[u][0];i++) {
int v=a[u][i];
if (!visited[v]) {
dfs1(v);
}
}
st.push(u);
}
void dfs2(int u) {
visited[u] = true;
comp[u] = cnt;
for (int i=1;i<=r[u][0];++i) {
int v=r[u][i];
if (!visited[v]) {
dfs2(v);
}
}
}
int main() {
freopen("cdrom.in","r",stdin);
freopen("cdrom.out","w",stdout);
n=read();
memset(a,0,sizeof(a));
memset(r,0,sizeof(r));
for (int i=1;i<=n;++i) {
int j;
while(cin>>j&&j!=0) {
a[i][++a[i][0]] = j;
r[j][++r[j][0]] = i;
}
}
memset(visited, 0, sizeof(visited));
for (int i=1;i<=n;++i) {
if (!visited[i]) {
dfs1(i);
}
}
memset(visited, 0, sizeof(visited));
cnt = 0;
while (!st.empty()) {
int u=st.top();
st.pop();
if (!visited[u]) {
cnt++;
dfs2(u);
}
}
memset(in_degree,0,sizeof(in_degree));
memset(has_edge,0,sizeof(has_edge));
for (int u =1;u<=n;++u) {
for (int i=1;i<=a[u][0];++i) {
int v=a[u][i];
int q=comp[u];
int b=comp[v];
if (q!=b&&!has_edge[q][b]) {
has_edge[q][b] = true;
in_degree[b]++;
}
}
}
int ans=0;
for (int i=1;i<=cnt;++i) {
if (in_degree[i] == 0) {
ans++;
}
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号