[UKIEPC 2017] 部分题解

枚举大法妙啊

今天比赛节奏把握相对还可以 队友都很优秀 %%tql  出了10个题 rank3 有史以来最高记录(叉会腰) 下面放AC代码 (除了 G 、H


  A - Alien Sunset

题目大意: 给n组日长、日出时间、日落时间,问是否能找到一个时间段点 使得n个行星都处于天黑中。

思路:暴力枚举模拟在1825 * 日长max 内 枚举每个小时是否每个行星都在天黑 如果能找到就输出 不能找到就输出impossible

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=30;
 5 int day[N],dx,rise[N],night[N];
 6 bool judge(int h, int i)
 7 {
 8     h%=day[i];
 9     if(rise[i] <= night[i] && (h<=rise[i] || h>=night[i])) return 1;
10     if(rise[i] >  night[i] && (h<=rise[i] && h>=night[i])) return 1;
11     return 0;
12 }
13 int main()
14 {
15     int n;
16     scanf("%d",&n);
17     for(int i=1; i<=n; i++)
18     {
19         scanf("%d%d%d",&day[i],&rise[i],&night[i]);
20         dx=max(dx, day[i]);
21     }
22     for(int i=0; i<dx * 1825; i++)
23     {
24         bool f=0;
25         for(int j=1; j<=n; j++) if(!judge(i, j)) {f=1; break;}
26         if(!f){printf("%d\n",i); return 0;}
27     }
28     puts("impossible");
29     return 0;
30 }
Alien Sunset

 B - Breaking Biscuits  (来自队友B

题目大意: 给一个凸n边形,求最小直径

思路:板子题 没思路 (板子是我搬的 但爱你是真的)

  
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const double eps = 1e-16;
  4 int sgn(double x)
  5 {
  6     if(fabs(x) < eps)return 0;
  7     if(x < 0)return -1;
  8     else return 1;
  9 }
 10 struct point
 11 {
 12     double x,y;
 13     point(int _x = 0,int _y = 0)
 14     {
 15         x = _x;
 16         y = _y;
 17     } point operator -(const point &b)const
 18     {
 19         return point(x - b.x, y - b.y);
 20     } double operator ^(const point &b)const
 21     {
 22         return x*b.y - y*b.x;
 23     } double operator *(const point &b)const
 24     {
 25         return x*b.x + y*b.y;
 26     } void sc()
 27     {
 28         scanf("%lf%lf",&x,&y);
 29     }
 30 };
 31 struct Line
 32 {
 33     point s,e;
 34     Line() {} Line(point _s,point _e)
 35     {
 36         s = _s;
 37         e = _e;
 38     } pair<int,point> operator &(const Line &b)const
 39     {
 40         point res = s;
 41         if(sgn((s-e)^(b.s-b.e)) == 0)
 42         {
 43             if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);
 44             else return make_pair(1,res);
 45         }
 46         double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
 47         res.x += (e.x-s.x)*t;
 48         res.y += (e.y-s.y)*t;
 49         return make_pair(2,res);
 50     }
 51 };
 52 double dist(point a,point b)
 53 {
 54     return (double)sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 55 }
 56 point NearestpointToLineSeg(point P,Line L)
 57 {
 58     point result;
 59     double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));
 60     if(t >= 0.000 && t <= 1.0000)
 61     {
 62         result.x = L.s.x + (L.e.x - L.s.x)*t;
 63         result.y = L.s.y + (L.e.y - L.s.y)*t;
 64     }
 65     else
 66     {
 67         if(dist(P,L.s) < dist(P,L.e)) result = L.s;
 68         else result = L.e;
 69     }
 70     return result;
 71 }
 72 double emmm(point P,Line L)
 73 {
 74     point zz=NearestpointToLineSeg(P,L);
 75     return dist(zz,P);
 76 }
 77 const int MAXN = 2e5+7;
 78 point List[MAXN];
 79 int Stack[MAXN],top;
 80 bool _cmp(point p1,point p2)
 81 {
 82     double tmp = (p1-List[0])^(p2-List[0]);
 83     if(tmp > 0)return true;
 84     else if(tmp == 0 && dist(p1,List[0]) <= dist(p2,List[0])) return true;
 85     else return false;
 86 }
 87 void Graham(int n)
 88 {
 89     point p0;
 90     int k = 0;
 91     p0 = List[0];
 92     for(int i = 1; i < n; i++)
 93     {
 94         if(p0.y > List[i].y || (p0.y == List[i].y && p0.x > List[i].x))
 95         {
 96             p0 = List[i];
 97             k = i;
 98         }
 99     }
100     swap(List[k],List[0]);
101     sort(List+1,List+n,_cmp);
102     if(n == 1)
103     {
104         top = 1;
105         Stack[0] = 0;
106         return;
107     }
108     if(n == 2)
109     {
110         top = 2;
111         Stack[0] = 0;
112         Stack[1] = 1;
113         return;
114     }
115     Stack[0] = 0;
116     Stack[1] = 1;
117     top = 2;
118     for(int i = 2; i < n; i++)
119     {
120         while(top > 1 && ((List[Stack[top-1]]-List[Stack[top-2]])^(List[i]-List[Stack[top-2]])) <= 0) top--;
121         Stack[top++] = i;
122     }
123 }
124 double rotating_calipers(point p[],int n)
125 {
126     double ans = 999999999999999999999.0;
127     point v;
128     int cur = 1;
129     for(int i = 0; i < n; i++)
130     {
131         v = p[i]-p[(i+1)%n];
132         while((v^(p[(cur+1)%n]-p[cur])) < 0)
133         {
134             cur = (cur+1)%n;
135         }
136         Line qw=Line(p[(i)%n],p[(i+1)%n]);
137         // point zz=NearestpointToLineSeg(p[cur],qw);
138         double as=emmm(p[cur],qw); //as=max(as,zx);
139         ans=min(ans,as);
140         // ans=min(ans,max(dist(p[i],p[cur]),dist(p[(i+1)%n],p[(cur+1)%n])));
141          }
142         return ans;
143     }
144     point p[MAXN];
145     int main()
146     {
147         int n,r;
148         scanf("%d",&n);
149             for(int i = 0; i < n; i++)List[i].sc();
150             Graham(n);
151             for(int i = 0; i < top; i++)p[i] = List[Stack[i]];
152             printf("%.7f\n",rotating_calipers(p,top));
153         return 0;
154     }
Breaking Biscuits

 C - Cued In

题目大意: 进一个红球后必须进非红球,除了红球之外的球都还可以再捞回来继续进球,没有红球时游戏结束。

思路:尽可能得进分值最高的球   (坑点)如果只有红球 则只能进一次红球

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=1009;
 5 int a[N];
 6 string s;
 7 map<string,int> psi;
 8 void init()
 9 {
10     psi["red"]=1;
11     psi["yellow"]=2;
12     psi["green"]=3;
13     psi["brown"]=4;
14     psi["blue"]=5;
15     psi["pink"]=6;
16     psi["black"]=7;
17 }
18 int main()
19 {
20     init();
21     int n;
22     scanf("%d",&n);
23     for(int i=0; i<n; i++)
24     {
25         cin>>s;
26         a[psi[s]]++;
27     }
28     if (a[1]==n) puts("1");
29     else
30     {
31         ll ans=0;
32         if (a[1])
33         {
34             int p=7;
35             while(!a[p]) --p;
36             ans+=p*a[1]+a[1];
37         }
38         for(int i=2; i<=7; i++) ans+=i*a[i];
39         cout<<ans<<endl;
40     }
41     return 0;
42 }
Cued In

 D - Deranging Hat

题目大意:给定一个序列 问怎样从正序序列到达这个序列

思路:根据题意模拟 但是每次模拟完要记得swap

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=2e3+10;
 5 char s1[N],s2[N];
 6 int main()
 7 {
 8     cin>>s2;
 9     strcpy(s1+1,s2);
10     strcpy(s2+1,s1+1);
11     int n=strlen(s2+1);
12     sort(s2+1,s2+1+n);
13   //  cout<<(s2+1)<<endl;
14     for(int i=1; i<=n; i++)
15     {
16         if(s1[i]!=s2[i])
17         {
18             for(int j=i+1; j<=n; j++)
19             {
20                 if(s2[j]==s1[i])
21                 {
22                     if(s2[i]>s2[j]) printf("%d %d\n",i,j);
23                     else printf("%d %d\n",j,i);
24                     swap(s2[j],s2[i]);
25                     break;
26                 }
27             }
28         }
29     }
30     return 0;
31 }
Deranging Hat

 

 E - Education (来自队友A

题目大意:(题目经过处理 只需要输出"possible" or "impossible") 分别给n、m个数 判断这n个数是否都能小于m个数里的某一个数(不能重复)

思路:排序+比较

  
 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 const int maxn = 1e5 + 100;
 4 const int INF = 1e9 + 7;
 5 using namespace std;
 6 int a[maxn],b[maxn];
 7 bool cmp(int x,int y)
 8 {
 9     return x>y;
10 }
11 int main() {
12     int n, m;
13     scanf("%d%d", &n, &m);
14     for(int i=1; i<=n; i++){
15         scanf("%d",&a[i]);
16     }
17     for(int i=1; i<=m; i++)
18         scanf("%d",&b[i]);
19     sort(a+1,a+n+1,cmp);
20     sort(b+1,b+m+1,cmp);
21     int v;
22     for(int i=1; i<=m; i++)
23         scanf("%d",&v);
24     int k=1;
25     for(int i=1; i<=m; i++){
26         if(b[i]>=a[k]){
27             k++;
28             if(k==n+1){
29                 printf("possible\n");
30                 return 0;
31             }
32         }
33     }
34     printf("impossible\n");
35     return 0;
36 }
Education

 F - Flipping Coins (来自队友B

题目大意:给n个面朝下的硬币,必须挑k个硬币抛 计算最后面朝上的硬币的期望

思路:概率dp

  
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <bits/stdc++.h>
const int N=1e6+10;
typedef long long ll;
using namespace std;

int n,m,k;
double dp[450][450],c[450][450],p[450];
void init(){
    c[0][0]=1;
    p[0]=1;
    for(int i=1;i<=420;i++){
        for(int j=0;j<=i;j++){
            if(!j||j==i) c[i][j]=1;
            else c[i][j]=c[i-1][j-1]+c[i-1][j];
        }
        p[i]=p[i-1]/2.0;
    }
}

int main()
{
    init();
        scanf("%d%d",&n,&m);
        int k=1;
        double ans=0.0;
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(int i=0;i<m;i++){
            for(int j=0;j<=n;j++){
                if(!dp[i][j]) continue;//剪枝
                for(int t=0;t<=k;t++){
                    if(j+k<=n){
                        dp[i+1][j+t]+=1.0*dp[i][j]*c[k][t]*p[k];
                    }
                    else{//j+k>n
                        int u=j+k-n;
                        dp[i+1][j-u+t]+=1.0*dp[i][j]*c[k][t]*p[k];
                    }
                }
            }
        }
        for(int i=1;i<=n;i++){
            ans+=i*dp[m][i];
        }
        printf("%.7lf\n",ans);
    return 0;
}
Flipping Coins

 I - I Work All Day (队友口述思路之后扔给我写

题目大意:给一个木头的总长,n个有用的长度,问最少能浪费多少,输出选择的长度。

思路:枚举 输出取余的最小值

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=19;
 4 int a[N];
 5 int main()
 6 {
 7     int n,m,f=0,ans=1;
 8     scanf("%d",&n);
 9     for(int i=1; i<=n; i++) scanf("%d",&a[i]);
10     scanf("%d",&m);
11     for(int i=2;i<=n;i++)
12         if(m%a[i]<m%a[ans]) ans=i;
13     printf("%d\n",a[ans]);
14     return 0;
15 }
I Work All Day

 J - Just A Minim (来自队友B

题目大意:给n个数 问数字出现的次数对应的值计算后的结果

思路:根据题意模拟

  
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+10;
int mp[20];
int n,x;
int main()
{
    scanf("%d",&n);
    double ans=0.0;
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        mp[x]++;
    }
    ans=mp[0]*2.0+mp[1]+mp[2]*0.5+mp[4]*0.25+mp[8]*0.125+mp[16]*0.0625;
    printf("%0.7lf\n",ans);
    return 0;
}
Just A Minim

 K - Knightsbridge Rises (来自队友A

题目大意:给n个起重机 m个最后要起重的重量 问是否能全都拉到楼顶 如果可以输出方案 不可以则输出"impossible"

思路:贪心 从m[i]往回搜寻 如果都能搜到0 就可以 否则 就不可以

  
 1 #include <bits/stdc++.h>
 2 
 3 typedef long long ll;
 4 const int maxn = 200;
 5 const int INF = 1e9 + 7;
 6 using namespace std;
 7 struct node {
 8     int f;
 9     int l, r;
10 } s[maxn];
11 int x[maxn];
12 int a[maxn][maxn];
13 
14 int main() {
15     int n;
16     scanf("%d", &n);
17     int zero = 0;
18     for (int i = 1; i <= n; i++) {
19         scanf("%d%d", &s[i].l, &s[i].r);
20         if (s[i].l == 0)
21             zero++;
22     }
23     int m;
24     scanf("%d", &m);
25     int flag = 1;
26     for (int i = 1; i <= m; i++)
27         scanf("%d", &x[i]);
28     if (zero < m) {
29         printf("impossible\n");
30         return 0;
31     }
32     for (int i = 1; i <= m; i++) {
33         int v = x[i], pos = -1, val = INF;
34         a[i][0] = 1;
35         while (v != 0) {
36             pos = -1;
37             val = INF;
38             for (int j = 1; j <= n; j++) {
39                 if (s[j].r >= v && s[j].f == 0) {
40                     if (s[j].r < val) {
41                         val = s[j].r;
42                         pos = j;
43                     }
44                 }
45             }
46             if (pos == -1) {
47                 flag = 0;
48                 break;
49             }
50             v = s[pos].l;
51             a[i][a[i][0]++] = pos;
52             s[pos].f = 1;
53         }
54         if (flag == 0) {
55             break;
56         }
57     }
58     if (flag == 0) {
59         printf("impossible\n");
60     } else {
61         for (int i = 1; i <= m; i++) {
62             for (int j = a[i][0] - 1; j > 0; j--) {
63                 if (j == 1)
64                     printf("%d", a[i][j]);
65                 else
66                     printf("%d ", a[i][j]);
67             }
68             printf("\n");
69         }
70     }
71     return 0;
72 }
73 //6
74 //0 0
75 //0 1
76 //1 2
77 //3 2
78 //0 3
79 //0 3
80 //3
81 //1 2 3
Knightsbridge Rises

 L - Lounge Lizards

题目大意:给电视机的坐标 给n个蜥蜴的坐标和高度 问最多能有几个蜥蜴能看到电视

思路:暴力+LIS 记录每个方向上能看到电视的max 最后累加就是ans

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef pair<int,int> pii;
 5 typedef pair<ll,int>pli;
 6 const int inf=0x3f3f3f3f,N=1e6+7;
 7 map<pii,int>m;
 8 int n,res,cnt,a[N],lis[N];
 9 vector<pli>g[N];
10 inline ll read()
11 {
12     int x=0,f=1;
13     char ch=getchar();
14     while(ch<'0'||ch>'9')
15     {
16         if(ch=='-')f=-1;
17         ch=getchar();
18     }
19     while(ch>='0'&&ch<='9')
20     {
21         x=x*10+ch-'0';
22         ch=getchar();
23     }
24     return x*f;
25 }
26 inline int gcd(int a,int b)
27 {
28     return b?gcd(b,a%b):a;
29 }
30 inline ll dis(int x,int y)
31 {
32     return (ll)x*x+(ll)y*y;
33 }
34 inline int LIS(int n)
35 {
36     for(int i=1; i<n; i++) lis[i]=inf;
37     lis[0]=a[0];
38     int len=1;
39     for(int i=0; i<n; i++)
40     {
41         if(a[i]>lis[len-1]) lis[len++]=a[i];
42         else
43         {
44             int p=lower_bound(lis, lis+len, a[i])-lis;
45             lis[p]=a[i];
46         }
47     }
48     return len;
49 }
50 inline void init(int x,int y,int h)
51 {
52     ll d=dis(x,y);
53     if(x==0) y/=abs(y);
54     else if(y==0) x/=abs(x);
55     else
56     {
57         int z=gcd(abs(x),abs(y));
58         x/=z,y/=z;
59     }
60     if(m.find(pii(x,y))==m.end())  m[pii(x,y)]=++res;
61     g[m[pii(x,y)]].push_back(pli(d,h));
62 }
63 int main()
64 {
65     int tx,ty,x,y,h;
66     tx=read(),ty=read(),n=read();
67     for(int i=1; i<=n; i++)
68     {
69         x=read(),y=read(),h=read();
70         x-=tx,y-=ty;
71         init(x,y,h);
72     }
73     int ans=0;
74     for(int i=1; i<=res; i++)
75     {
76         sort(g[i].begin(),g[i].end());
77         cnt=g[i].size();
78         for(int j=0; j<cnt; j++) a[j]=g[i][j].second;
79         ans+=LIS(cnt);
80     }
81     printf("%d\n",ans);
82     return 0;
83 }
Lounge Lizards

猜你喜欢

转载自www.cnblogs.com/lorelei/p/9550176.html