题目来自UKIEPC2017
A题:Alien Sunset
有n个星球,输入每个星球一天的时间,日出和日落的时间。从日落到日出(包括日出、日落)是黑夜。其他的为白天。问在前1825天里能不能有一个时辰满足所有的星球都是夜晚。
直接模拟
1 #include2 using namespace std; 3 bool ap[200050]; 4 int main() 5 { 6 int n,hh; 7 scanf("%d",&n); 8 hh=0; 9 int h,r,t; 10 while(n--) 11 { 12 scanf("%d %d %d",&h,&r,&t); 13 hh=max(h,hh); 14 r++; 15 t++; 16 if(t<r) 17 { 18 for(int i=1;i ) 19 ap[i]=1; 20 t=t+h; 21 } 22 int cnt; 23 for(int i=r+1;i<=t-1;i++) 24 { 25 cnt=0; 26 while(i+h*cnt<=183000) 27 { 28 ap[i+h*cnt]=1; 29 cnt++; 30 } 31 } 32 } 33 for(int i=1;i<=hh*1825;i++) 34 if(ap[i]==0) 35 { 36 printf("%d\n",i-1); 37 return 0; 38 } 39 printf("impossible\n"); 40 return 0; 41 }
B题:Breaking Biscuits
给出一个二维多边形按逆时针方向的坐标,让该多边形的某一方向能放在一个长方形里,求该长方形的最小宽度。
根据给出的点建立凸包,然后枚举凸包的每条边,计算凸包的其他点到该边的最大值,然后再找到这些最大值的最小值
1 #include2 3 using namespace std; 4 struct Point //定义点 5 { 6 double x,y; 7 Point(double x=0,double y=0):x(x),y(y){} 8 }; 9 typedef Point Vector; 10 bool cmp(Point a,Point b) //排序方式 11 { 12 return a.x b.y); 13 } 14 Vector operator - (Point A,Point B){ return Vector(A.x-B.x,A.y-B.y);}//重载减法号 15 double Cross(Vector A,Vector B) 16 { 17 return A.x*B.y-A.y*B.x; 18 } 19 double Dot(Vector A,Vector B) 20 { 21 return A.x*B.x+A.y*B.y; 22 } 23 double Length(Vector A) 24 { 25 return sqrt(Dot(A,A)); 26 } 27 int n; 28 Point ch[200],p[200]; 29 int ConvexHull() //凸包模板 30 { 31 sort(p,p+n,cmp); 32 int m=0; 33 for(int i=0;i ) 34 { 35 while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; 36 ch[m++]=p[i]; 37 } 38 int k=m; 39 for(int i=n-2;i>=0;i--) 40 { 41 while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--; 42 ch[m++]=p[i]; 43 } 44 if(n>1) m--; 45 return m; 46 } 47 double Distance(Point P,Point A,Point B) //点P到AB边的距离 48 { 49 Vector v1=B-A,v2=P-A; 50 return fabs(Cross(v1,v2))/Length(v1); 51 } 52 int main() 53 { 54 // freopen("in.txt","r",stdin); 55 56 scanf("%d",&n); 57 for(int i=0;i ) 58 { 59 scanf("%lf%lf",&p[i].x,&p[i].y); 60 } 61 int nn=ConvexHull(); 62 double maxn,minn=(double)1000000007; 63 for(int i=1;i //枚举每条边 64 { 65 maxn=-1; 66 if(i>1) 67 { 68 for(int j=0;j 1;j++) 69 { 70 if(Distance(ch[j],ch[i],ch[i-1])>maxn) 71 maxn=Distance(ch[j],ch[i],ch[i-1]); 72 } 73 } 74 for(int j=i+1;j ) 75 { 76 if(Distance(ch[j],ch[i],ch[i-1])>maxn) 77 maxn=Distance(ch[j],ch[i],ch[i-1]); 78 } 79 if(maxn<minn) 80 minn=maxn; 81 } 82 maxn=-1; 83 for(int i=1;i 1;i++) //不要忘了ch[nn-1]ch[0]这条边 84 { 85 if(Distance(ch[i],ch[0],ch[nn-1])>maxn) 86 maxn=Distance(ch[i],ch[0],ch[nn-1]); 87 } 88 if(maxn<minn) 89 minn=maxn; 90 printf("%.6lf\n",minn); 91 return 0; 92 }
C题:Cued In
直接模拟
1 #include2 3 using namespace std; 4 5 int main() 6 { 7 int a[10]={ 0}; 8 int n; 9 cin>>n; 10 string s; 11 for(int i=0;i ) 12 { 13 cin>>s; 14 if(s=="yellow") a[2]++; 15 else if(s=="green") a[3]++; 16 else if(s=="brown") a[4]++; 17 else if(s=="blue") a[5]++; 18 else if(s=="pink") a[6]++; 19 else if(s=="black") a[7]++; 20 else a[1]++; 21 } 22 int pos; 23 for(int i=7;i>=1;i--) 24 { 25 if(a[i]) 26 { 27 pos = i; 28 break; 29 } 30 } 31 int ans = 0; 32 if(pos==1) 33 { 34 cout<<1<<endl; 35 return 0; 36 } 37 else 38 ans += (1+pos)*a[1]; 39 40 for(int i=pos;i>=2;i--) 41 ans+=a[i]*i; 42 cout< endl; 43 return 0; 44 }
D题:Deranging Hat
直接按照题目意思做
1 #include2 using namespace std; 3 char s[1005]; 4 int main() 5 { 6 scanf("%s",s); 7 int len=strlen(s); 8 int a[100005],b[100005],cnt1=0; 9 for(int i=0;i ) 10 { 11 for(int j=i+1;j ) 12 { 13 if(s[i]>s[j]) 14 { 15 a[cnt1]=i+1; 16 b[cnt1]=j+1; 17 cnt1++; 18 swap(s[i],s[j]); 19 } 20 } 21 } 22 for(int i=cnt1-1;i>=0&&i>=cnt1-10000;i--) 23 { 24 printf("%d %d\n",b[i],a[i]); 25 } 26 return 0; 27 }
E题:Education
该题与原题输出不同,请注意!
对于该题来说,直接写。
1 #include2 3 using namespace std; 4 5 const int maxn = 5005; 6 7 int main() 8 { 9 int n,m; 10 cin>>n>>m; 11 int a[maxn]; 12 int b[maxn]; 13 for(int i=0;i ) 14 cin>>a[i]; 15 for(int i=0;i ) 16 cin>>b[i]; 17 int x; 18 for(int i=0;i ) 19 cin>>x; 20 sort(a,a+n); 21 sort(b,b+m); 22 int now = 0; 23 for(int i=0;i ) 24 { 25 if(a[now]<=b[i]) 26 now++; 27 if(now==n) 28 break; 29 } 30 if(now==n) 31 { 32 cout<<"possible"<<endl; 33 return 0; 34 } 35 else 36 { 37 cout<<"impossible"<<endl; 38 return 0; 39 } 40 return 0; 41 }
F题:Flipping Coins
1 #include2 using namespace std; 3 typedef long long ll; 4 double dp[405][405]; 5 int main() 6 { 7 int n,k; 8 scanf("%d%d",&n,&k); 9 dp[0][0] = 1; 10 for(int i=0; i ) 11 { 12 for(int j=0; j<=n; j++) 13 { 14 if(dp[i][j]==0) 15 continue; 16 if(n-j>=1) 17 { 18 dp[i+1][j+1] += dp[i][j]*0.5; 19 dp[i+1][j] += dp[i][j]*0.5; 20 } 21 else 22 { 23 dp[i+1][j] += dp[i][j]*0.5; 24 dp[i+1][j-1] += dp[i][j]*0.5; 25 } 26 } 27 } 28 double ans = 0; 29 for(int i=1;i<=n;i++) 30 ans+=dp[k][i]*i; 31 printf("%.6f",ans); 32 return 0; 33 }
I题:I Work All Day
求能产生最大余数的那个数
1 #include2 3 using namespace std; 4 int n,h[100],t; 5 int main() 6 { 7 scanf("%d",&n); 8 for(int i=0;i ) 9 scanf("%d",&h[i]); 10 scanf("%d",&t); 11 int tmp,pos,ans=3005; 12 for(int i=0;i ) 13 { 14 tmp=t%h[i]; 15 if(tmp<ans) 16 { 17 ans=tmp; 18 pos=i; 19 } 20 } 21 printf("%d\n",h[pos]); 22 return 0; 23 }
J题:Just A Minim
直接按照题意写
1 #include2 3 using namespace std; 4 5 int main() 6 { 7 int op,n; 8 double ans=0; 9 scanf("%d",&n); 10 while(n--) 11 { 12 scanf("%d",&op); 13 if(op==0) 14 { 15 ans+=2; 16 } 17 else 18 { 19 ans+=(double)1.0/(op*1.0); 20 } 21 } 22 printf("%.6lf\n",ans); 23 return 0; 24 }
L题:Lounge Lizards
给出电视机的坐标,有n个人,分别输入他们的坐标和高度,可以把某些人赶出去,问最多能有多少人能看到电视
首先求出每个人与电视机的方向向量,并约分,然后对于每组求LIS,最后取和
1 #include2 3 using namespace std; 4 typedef long long ll; 5 int n; 6 const int inf=0x3f3f3f3f; 7 const int maxn = 1e6+5; 8 struct P 9 { 10 int x,y,h; 11 ll dis; 12 }a[maxn],o; 13 int dp[maxn]; 14 int gcd(int a,int b) 15 { 16 return b?gcd(b,a%b):a; 17 } 18 bool cmp(P a,P b) 19 { 20 if(a.x!=b.x) return a.x<b.x; 21 else if(a.y!=b.y) return a.y<b.y; 22 else return a.dis<b.dis; 23 } 24 int f(int l,int r) //O(nlog(n))的复杂度 25 { 26 int idx=1,where; 27 // for(int i=l;i //初始化可加也不可加 28 // dp[i]=inf; 29 dp[idx]=a[l].h; 30 for(int i=l+1;i 31 { 32 if(a[i].h>dp[idx]) 33 { 34 idx++; 35 dp[idx]=a[i].h; 36 } 37 else 38 { 39 where=lower_bound(dp+1,dp+idx+1,a[i].h)-dp; 40 dp[where]=a[i].h; 41 } 42 } 43 return idx; 44 } 45 int main() 46 { 47 scanf("%d%d",&o.x,&o.y); 48 scanf("%d",&n); 49 for(int i=0; i) ) 50 { 51 scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].h); 52 a[i].x -= o.x; 53 a[i].y -= o.y; 54 a[i].dis = (ll)a[i].x*a[i].x + (ll)a[i].y*a[i].y; //注意要在每一项上加上(ll) 55 int t = gcd(abs(a[i].x),abs(a[i].y)); 56 a[i].x/=t; 57 a[i].y/=t; 58 } 59 sort(a,a+n,cmp); //排序 60 int j; 61 int ans = 0; 62 for(int i=0; i j) 63 { 64 j = i+1; 65 while(j //求相同的方向向量 66 { 67 j++; 68 } 69 ans += f(i,j); //求LIS 70 } 71 printf("%d\n",ans); 72 return 0; 73 }
K题:Knightsbridge Rises
拆点求最大流问题
思路参考https://blog.csdn.net/V5ZSQ/article/details/80472491
n个吊车拆成两排n个点,m个建筑物看作m个点
1、源点向所有自身重量为0的吊车连容量为1的边
2、每个吊车拆成的第一个点向第二个点连容量为1的边
3、如果Li>=Wj,那么第i个吊车拆成的第二个点向第j个吊车拆成的第一个点连容量为1的边
4、如果Li>=Tj,那么第i个吊车拆成的第二个点向第j个建筑物连容量为1的边
5、每个建筑物向汇点连容量为1的边
用最大流是否为m来判断是否所有建筑物都可以被吊起,然后再dfs,寻找路径
代码参考 https://www.cnblogs.com/clrs97/p/7768748.html
1 #include2 using namespace std; 3 const int maxn=300; 4 const int maxe=4*maxn*maxn; 5 const int inf=0x3f3f3f3f; 6 #define MS(x,y) memset(x,y,sizeof(x)) 7 int head[maxn],tot,n,m; 8 int w[maxe],cap[maxe],nxt[maxe]; 9 void add(int u,int v,int f) //存边 10 { 11 w[++tot]=v; 12 cap[tot]=f; 13 nxt[tot]=head[u]; 14 head[u]=tot; 15 16 w[++tot]=u; 17 cap[tot]=0; 18 nxt[tot]=head[v]; 19 head[v]=tot; 20 } 21 int d[maxn],ST,ED; 22 bool bfs() 23 { 24 MS(d,-1); 25 queue<int>q; 26 q.push(ST); 27 d[ST]=0; 28 while(!q.empty()) 29 { 30 int u=q.front();q.pop(); 31 for(int i=head[u];i;i=nxt[i]) 32 if(cap[i]) 33 { 34 int v=w[i]; 35 if(d[v]==-1) 36 { 37 d[v]=d[u]+1; 38 q.push(v); 39 if(v==ED) return 1; 40 } 41 42 } 43 } 44 return 0; 45 } 46 int dfs(int x,int all) 47 { 48 if(x==ED) return all; 49 int use=0; 50 for(int i=head[x];i;i=nxt[i]) if(cap[i]) 51 { 52 int y=w[i]; 53 if(d[y]==d[x]+1) 54 { 55 int tmp=dfs(y,min(cap[i],all-use)); 56 cap[i]-=tmp; 57 cap[i^1]+=tmp; 58 use+=tmp; 59 if(use==all) break; 60 } 61 } 62 if(use==0) d[x]=-1; 63 return use; 64 } 65 int dinic() 66 { 67 int ret=0; 68 while(bfs()) ret+=dfs(ST,inf); 69 return ret; 70 } 71 vector<int>vt[maxn]; 72 void dfs_path(int cur,int x) //寻找路径 73 { 74 for(int i=head[x];i;i=nxt[i]) if((i&1)&&cap[i]) 75 { 76 x=w[i]; 77 break; 78 } 79 if(x==0) return ; 80 vt[cur].push_back(x-n); 81 dfs_path(cur,x-n); 82 } 83 int W[maxn],L[maxn]; 84 int main() 85 { 86 scanf("%d",&n); 87 MS(head,0); 88 tot=1; 89 ST=0; 90 for(int i=1;i<=n;i++) 91 { 92 scanf("%d%d",&W[i],&L[i]); 93 if(W[i]==0) 94 add(ST,i,1); 95 add(i,n+i,1); 96 } 97 for(int i=1;i<=n;i++) 98 { 99 for(int j=1;j<=n;j++) if(i!=j&&L[i]>=W[j]) 100 { 101 add(n+i,j,1); 102 } 103 } 104 scanf("%d",&m); 105 ED=2*n+m+1; 106 int xx; 107 for(int i=1;i<=m;i++) 108 { 109 scanf("%d",&xx); 110 add(2*n+i,ED,1); 111 for(int j=1;j<=n;j++) if(L[j]>=xx) 112 { 113 add(n+j,2*n+i,1); 114 } 115 } 116 if(dinic()==m) 117 { 118 for(int i=head[ED];i;i=nxt[i]) if((i&1)&&cap[i]) 119 { 120 vt[w[i]-2*n].clear(); 121 dfs_path(w[i]-2*n,w[i]); 122 } 123 for(int i=1;i<=m;i++) 124 { 125 for(int j=vt[i].size()-1;j>=0;j--) 126 { 127 if(j!=vt[i].size()-1) printf(" "); 128 printf("%d",vt[i][j]); 129 } 130 printf("\n"); 131 } 132 } 133 else 134 printf("impossible\n"); 135 return 0; 136 137 }