前言
发现自己又“独树一帜”了一回,和大家的思路都不同...可惜没调出来,挖坑以后再调吧...
题目
分析
(直接看正解见横线以下)
自己的思路(没调过):
如果要构成一个正K边形,在圆上肯定要有K个相等的大线段,
设这K个相等的大线段长度为len,len = C / k
这些大线段又由许多初始点构成的小线段构成
所以对于圆上的每个小线段d[ i ],有以下三种情况:(设已有的大线段数量为cnt,已访问过的线段为tot)
1.d[ i ]=len:长度直接符合,cnt++
2.d[ i ]>len:因为小线段不能拆分,于是直接无解,print “No”
3.d[ i ]<len:要和其他线段(长度也小于len)合起来,使得长度等于len,就要看是和其左边的线段合起来,还是和右边的线段合起来
最后如果tot=n且cnt=k,则“Yes”,否则“No”
我是用的搜索实现的,不过很遗憾,只有30分,错因不明,只好学习别人的做法了
后来去问了一下某Tao大佬,好像说我没有考虑和左右线段一起合起来的情况...
AC代码思路:
形成K边形时,选中的K个点肯定相距都为len = C / k,所以对于每个点,找到和它相距len的点,
如果同属于一个并查集就“Yes”,否则就加入一个并查集,没有解就“No”
在一个并查集就相当于它们都属于构成某K边形的点or边的集合
PS.我也不知道我理解对了没有QAQ!
官方题解:
玄学搜索30分代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1e5;
bool vis[MAXN+5];
int a[MAXN+5],d[2*MAXN+5];
int n,c,k;
int len;
void dfs(int id,int cnt,int tot)
{
tot++,vis[id]=1;
if(d[id]==len)
cnt++;
//printf("id:%d cnt:%d tot:%d d:%d\n",id,cnt,tot,d[id]);
if(cnt==k&&tot==n)
{
printf("Yes\n");
exit(0);
}
if(tot==n)
return ;
if(d[id]==len)
{
int x=id+1,y=id-1;
if(x==n+1) x=1;
if(y==0) y=n;
if(!vis[x])
dfs(x,cnt,tot);
if(!vis[y])
dfs(y,cnt,tot);
}
if(d[id]>len)
{
printf("No\n");
exit(0);
}
if(d[id]<len)
{
int x=id+1,y=id-1;
if(x==n+1) x=1;
if(y==0) y=n;
if(!vis[x]&&d[x]+d[id]<=len)
{
d[x]+=d[id];
dfs(x,cnt,tot);
d[x]-=d[id];
}
if(!vis[y]&&d[y]+d[id]<=len)
{
d[y]+=d[id];
dfs(y,cnt,tot);
d[y]-=d[id];
}
}
vis[id]=0;
}
int main()
{
scanf("%d%d%d",&n,&c,&k);
len=c/k;
for(int i=2;i<=n;i++)
{
scanf("%d",&a[i]);
d[i-1]=a[i]-a[i-1];
}
d[n]=c-a[n];
dfs(1,0,0);
printf("No\n");
return 0;
}
AC代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1e5;
int a[MAXN+5],fa[MAXN+5];
int n,c,k,len;
int Find(int x)
{
return x==fa[x]?x:fa[x]=Find(fa[x]);
}
int main()
{
scanf("%d%d%d",&n,&c,&k);
len=c/k;
for(int i=2;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=n;i++)
{
int j=lower_bound(a+1,a+n+1,(a[i]+len)%c)-a;
if(j<=n&&a[j]==(a[i]+len)%c)
{
if(Find(i)==Find(j))
{
printf("Yes\n");
return 0;
}
fa[Find(i)]=Find(j);
}
}
printf("No\n");
return 0;
}
总结
我始终觉得自己的思路是可行的...只是不知道实现时哪里出了问题...qwq.../执着