https://codeforc.es/gym/102012/problem/M
我太难了!写了个垃圾代码wa了三天一直过不去最后代码又长又丑果断放弃。。。
题意
n个点,m个灯,问最少用多少个灯可以照亮全部点。
题解
显然贪心。
处理出每个灯的覆盖范围,贪心搞出保证覆盖当前点j的同时能往后覆盖的最大距离add[j],
最后枚举以每个点为起点的所需灯数,取最少情况输出即可。
1 #define bug(x) cout<<#x<<" is "<<x<<endl 2 #define IO std::ios::sync_with_stdio(0) 3 #define ull unsigned long long 4 #include <bits/stdc++.h> 5 #define iter ::iterator 6 #define pa pair<int,ll> 7 #define pp pair<int,pa> 8 using namespace std; 9 #define ll long long 10 #define mk make_pair 11 #define pb push_back 12 #define se second 13 #define fi first 14 #define ls o<<1 15 #define rs o<<1|1 16 const int N=1e5+5; 17 ll mod=998244353; 18 struct Point{ 19 int x,y; 20 }; 21 Point operator -(Point A,Point B){ 22 return (Point){A.x-B.x,A.y-B.y}; 23 } 24 ll Cross(Point A,Point B){ 25 return (1ll*A.x*B.y-1ll*A.y*B.x); 26 } 27 Point p[N],t[N]; 28 int add[N],id[N]; 29 int T,n,m; 30 int main(){ 31 scanf("%d",&T); 32 while(T--){ 33 scanf("%d%d",&n,&m); 34 for(int i=0;i<n+m;i++){ 35 add[i]=id[i]=0; 36 } 37 for(int i=0;i<n;i++){ 38 scanf("%d%d",&p[i].x,&p[i].y); 39 } 40 for(int i=0;i<m;i++){ 41 scanf("%d%d",&t[i].x,&t[i].y); 42 } 43 for(int i=0;i<m;i++){ 44 int l=0,r=0; 45 for(int j=1;j<n;j++){ 46 if(Cross(p[j]-t[i],p[l]-t[i])<0)l=j; 47 if(Cross(p[j]-t[i],p[r]-t[i])>0)r=j; 48 } 49 for(int j=l;j!=r;j=(j+1)%n){ 50 j%=n; 51 if(add[j]<(r-j+n)%n)add[j]=(r-j+n)%n,id[j]=i; 52 } 53 } 54 int f=0; 55 for(int i=0;i<n;i++){ 56 if(!add[i]){ 57 f=1; 58 break; 59 } 60 } 61 if(f){ 62 printf("-1\n"); 63 continue; 64 } 65 int ans=1e9,start=0; 66 for(int i=0;i<n;i++){ 67 int cnt=0; 68 int j=i; 69 while(j<i+n){ 70 j+=add[j%n]; 71 cnt++; 72 } 73 if(cnt<ans){ 74 ans=cnt; 75 start=i; 76 } 77 } 78 printf("%d\n",ans); 79 int i=start; 80 while(ans--){ 81 printf("%d%c",id[i]+1,ans==0?'\n':' '); 82 i+=add[i]%n; 83 } 84 } 85 }