博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)
阅读量:7029 次
发布时间:2019-06-28

本文共 10153 字,大约阅读时间需要 33 分钟。

A. Alien Sunset

暴力枚举答案即可。

#include
int n,i,mx;struct P{ int h,r,t; bool night(int x){ x%=h; if(r<=t)return x<=r||x>=t; return x<=r&&x>=t; } }a[50];inline bool check(int x){ for(int i=0;i
mx)mx=a[i].h; } for(i=0;i<1825*mx;i++)if(check(i))return printf("%d",i),0; puts("impossible");}

  

B. Breaking Biscuits

等价于选择一对距离最小的平行线夹住所有点。

枚举一条边,计算两侧所有点到这条直线的距离的最大值即可。

时间复杂度$O(n^3)$。

#include
#include
#include
using namespace std;const int N=111;struct P{ int x,y; P(){} P(int _x,int _y){x=_x,y=_y;} P operator-(P b){return P(x-b.x,y-b.y);} double len(){return hypot(x,y);}}a[N];int n,i,j,k;double cross(P a,P b){return a.x*b.y-a.y*b.x;}double dist(P p,P a,P b){ return cross(p-a,b-a)/(b-a).len();}int main(){ scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y); double ans=1e100; a[n+1]=a[1]; for(i=1;i<=n;i++)for(j=1;j

  

C. Cued In

按题意模拟即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N = 3e5 + 10;const int inf = 1e9;int casenum, casei;int c[2010], e[15];int n;map
mop;int num[10];char s[20];int main(){ mop["red"] = 1; mop["yellow"] = 2; mop["green"] = 3; mop["brown"] = 4; mop["blue"] = 5; mop["pink"] = 6; mop["black"] = 7; while(~scanf("%d", &n)){ for(int i = 1; i <= n; i ++){ scanf("%s", s); num[mop[s]] ++; } int top = 1; for(int i = 2; i <= 7; i ++){ if(num[i]) top = i; } if(top == 1) puts("1"); else{ int ans = 0; ans = (1 + top) * num[1]; for(int i = 2; i <= 7; i ++) ans += num[i] * i; printf("%d\n", ans); } } return 0;}/**/

  

D. Deranging Hat

求出最终位置,然后贪心置换即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N = 1e5 + 10;char s[N];struct A{ char ch; int now; bool operator < (const A & b)const { if(ch != b.ch)return ch < b.ch; return now < b.now; }}a[N];int pos_to_o[N];int main(){ while(~scanf("%s", s)) { int n = strlen(s); for(int i = 0; i < n; ++i) { a[i].ch = s[i]; a[i].now = i; } sort(a, a + n); for(int i = 0; i < n; ++i) { pos_to_o[a[i].now] = i; } vector
>ans; for(int i = 0; i < n; ++i) { //我们要考虑移动,把位置为a[i].now的数,移动到位置i,那位置i的数的位置变成了a[i].now if(a[i].now != i) { ans.push_back(make_pair(i, a[i].now)); int p = a[i].now; int o = pos_to_o[i]; a[o].now = a[i].now; pos_to_o[p] = o; } } int g = ans.size() - 1; for(int i = g; i >= 0; --i) { printf("%d %d\n", ans[i].second + 1, ans[i].first + 1); } } return 0;}/**/

  

E. Education

按人数从大到小考虑,每次选择满足条件的最便宜的房子。

#include
#include
using namespace std;const int N=5010;int n,m,i,a[N],b[N],c[N],q[N],ans[N];bool cmp(int x,int y){return a[x]
>1; for(int i=1;i<=m;i++)if(b[i]>=x){ if(c[i]

  

F. Flipping Coins

$f[i][j]$表示还需要操作$i$次,目前有$j$枚硬币朝上时的最大期望正面向上的硬币数。

时间复杂度$O(nk)$。

#include
#include
using namespace std;const int N=444;double f[N][N],ans;int n,m,i,j;int main(){ scanf("%d%d",&n,&m); for(i=1;i<=n;i++)f[0][i]=i; for(i=1;i<=m;i++)for(j=0;j<=n;j++){ if(j)f[i][j]=(f[i-1][j]+f[i-1][j-1])/2; if(j

  

G. GentleBots

设估价函数为两点到终点的曼哈顿距离之和,每次选取使得估价函数最优的方向走,若不能走,则随机抖动。

#include
#include
#include
#include
using namespace std;const int dx[7]={1,-1,0,0,0,0,0}, dy[7]={0,0,-1,1,0,0,0}, dz[7]={0,0,0,0,1,-1,0};struct P{ int x,y,z; void read(){ scanf("%d%d%d",&x,&y,&z); } int dis(P b){ return abs(x-b.x)+abs(y-b.y)+abs(z-b.z); } void write(){ printf("(%d %d %d)",x,y,z); } P(){} P(int _x,int _y,int _z){x=_x,y=_y,z=_z;} P apply(int d){ return P(x+dx[d],y+dy[d],z+dz[d]); }}A,B,C,D;//A->B C->Dint main(){ A.read(); B.read(); C.read(); D.read(); while(1){ A.write(); putchar(' '); C.write(); puts(""); int pre=A.dis(B)+C.dis(D); if(!pre)return 0; int best=~0U>>1; int I=0,J=0; for(int i=0;i<7;i++)for(int j=0;j<7;j++){ P NA=A.apply(i),NC=C.apply(j); if(!NA.dis(C))continue; if(!NA.dis(NC))continue; if(!NC.dis(A))continue; if(!NC.dis(NA))continue; int now=NA.dis(B)+NC.dis(D); if(now
=pre){ while(1){ int i=rand()%7,j=rand()%7; P NA=A.apply(i),NC=C.apply(j); if(!NA.dis(C))continue; if(!NA.dis(NC))continue; if(!NC.dis(A))continue; if(!NC.dis(NA))continue; I=i,J=j; break; } } A=A.apply(I); C=C.apply(J); }}

  

H. Hiker Safety

能走就走,用队列维护所有可能走的人,时间复杂度$O(n^2)$。

#include
const int N=10010;int B,m,i,n,d[N],a[N],pos[N],r;int h,t,x,q[10000000];int cnt,fin[3333333];inline int abs(int x){return x>0?x:-x;}inline bool check(int x){ if(pos[x]==m)return 0; int pre=x-1,nxt=x+1; if(nxt>r)nxt=0; if(pre){ if(abs(d[pos[x]+1]-d[pos[pre]])>B)return 0; if(abs(d[pos[x]+1]-d[pos[pre]])
B)return 0; if(abs(d[pos[x]+1]-d[pos[nxt]])
%d\n",x); pos[x]++; fin[++cnt]=x; while(r&&pos[r]==m)r--; if(x>1)q[++t]=x-1; if(x
d[i+1])while(1); scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d%d",&a[i],&pos[i]); } for(i=1;i<=n;i++){ if(pos[i]

  

I. I Work All Day

按题意模拟即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N = 3e5 + 10;const int inf = 1e9;int casenum, casei;int c[15], e[15];int n;int main(){ while(~scanf("%d", &n)) { for(int i = 0; i < n; ++i)scanf("%d", &c[i]); int T; scanf("%d", &T); int ans = c[0]; int val = T % c[0]; for(int i = 1; i < n; ++i) { if(T % c[i] < val) { val = T % c[i]; ans = c[i]; } } printf("%d\n", ans); } return 0;}/**/

  

J. Just A Minim

按题意模拟即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N = 3e5 + 10;const int inf = 1e9;int casenum, casei;int c[2010], e[15];int n;int main(){ while(~scanf("%d", &n)) { for(int i = 0; i < n; ++i)scanf("%d", &c[i]); double ans = 0; for(int i = 0; i < n; i ++){ if(c[i] == 0) ans += 2; else if(c[i] == 1) ans += 1; else if(c[i] == 2) ans += 0.5; else if(c[i] == 4) ans += 0.25; else if(c[i] == 8) ans += 0.125; else if(c[i] == 16) ans += 0.0625; } printf("%.8f\n", ans); } return 0;}/**/

  

K. Knightsbridge Rises

拆点求最大流。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;const int N = 305, M = N * N * 8;const int inf = 0x3f3f3f3f;#define MS(x, y) memset(x, y, sizeof(x))int n;int L[N], W[N];int ST, ED;int first[N], ID;int w[M], cap[M], nxt[M];void ins(int x, int y, int cap_){ w[++ID] = y; cap[ID] = cap_; nxt[ID] = first[x]; first[x] = ID; w[++ID] = x; cap[ID] = 0; nxt[ID] = first[y]; first[y] = ID;}int d[N];bool bfs(){ MS(d, -1); queue
q; q.push(ST); d[ST] = 0; while(!q.empty()) { int x = q.front(); q.pop(); for(int z = first[x]; z; z = nxt[z])if(cap[z]) { int y = w[z]; if(d[y] == -1) { d[y] = d[x] + 1; q.push(y); if(y == ED)return 1; } } } return 0;}int dfs(int x, int all){ if(x == ED)return all; int use = 0; for(int z = first[x]; z; z = nxt[z])if(cap[z]) { int y = w[z]; if(d[y] == d[x] + 1) { int tmp = dfs(y, min(cap[z], all - use)); cap[z] -= tmp; cap[z ^ 1] += tmp; use += tmp; if(use == all)break; } } if(use == 0)d[x] = -1; return use;}int dinic(){ int ret = 0; while(bfs())ret += dfs(ST, inf); return ret;}vector
vt[N];void go(int o, int x){ for(int z = first[x]; z; z = nxt[z])if((z & 1) && cap[z]) { x = w[z]; break; } if(x == 0) { //for(auto it : vt[o]) /* int cnt = 0; for(int ii = 0; ii < vt[o].size(); ++ii) { int it = vt[o][ii]; if(++cnt == 1)printf("%d", it); else printf(" %d", it); } puts(""); */ return; } vt[o].push_back(x - n); go(o, x - n);}int main(){ while(~scanf("%d", &n)) { MS(first, 0); ID = 1; ST = 0; for(int i = 1; i <= n; ++i) { scanf("%d%d", &W[i], &L[i]); if(W[i] == 0) { ins(ST, i, 1); } ins(i, n + i, 1); } for(int i = 1; i <= n; ++i) { for(int j = 1; j <= n; ++j)if(j != i && L[i] >= W[j]) { ins(n + i, j, 1); } } int m; scanf("%d", &m); ED = n + n + m + 1; for(int i = 1; i <= m; ++i) { int x; scanf("%d", &x); ins(n + n + i, ED, 1); for(int j = 1; j <= n; ++j)if(L[j] >= x) { ins(n + j, n + n + i, 1); } } if(dinic() != m) { puts("impossible"); } else { for(int z = first[ED]; z; z = nxt[z])if((z & 1) && cap[z]) { vt[w[z] - n - n].clear(); go(w[z] - n - n, w[z]); } for(int o = 1; o <= m; ++o) { int cnt = 0; for(int ii = vt[o].size() - 1; ii >= 0; --ii) { int it = vt[o][ii]; if(++cnt == 1)printf("%d", it); else printf(" %d", it); } puts(""); } } } return 0;}/*50 11 22 33 40 224 270 11 40 30 12 52 51 235 4 520 15 322 1*/

  

L. Lounge Lizards

将所有点到原点的方向向量约分后分组,每组按距离从小到大排序,然后求LIS。

时间复杂度$O(n\log n)$。

#include
#include
using namespace std;typedef long long ll;const int N=1000010;int n,i,j,k,m,f[N],ans;struct P{int x,y,h;ll w;}a[N],O;ll sqr(ll x){return x*x;}int gcd(int a,int b){return b?gcd(b,a%b):a;}inline bool cmp(const P&a,const P&b){ if(a.x!=b.x)return a.x
f[m]){ f[++m]=x; return; } int l=1,r=m,mid,t; while(l<=r){ mid=(l+r)>>1; if(f[mid]>=x)r=(t=mid)-1;else l=mid+1; } f[t]=x;}int main(){ scanf("%d%d",&O.x,&O.y); scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].h); a[i].x-=O.x; a[i].y-=O.y; a[i].w=sqr(a[i].x)+sqr(a[i].y); //sgn gcd int d=gcd(abs(a[i].x),abs(a[i].y)); a[i].x/=d,a[i].y/=d; //printf("%d %d %lld\n",a[i].x,a[i].y,a[i].w); } sort(a+1,a+n+1,cmp); for(i=1;i<=n;i=j){ for(j=i;j<=n&&a[i].x==a[j].x&&a[i].y==a[j].y;j++); m=0; for(k=i;k

  

转载地址:http://oarxl.baihongyu.com/

你可能感兴趣的文章