UPC2018组队训练赛第六场

题目来自UKIEPC2017


 

A题:Alien Sunset

有n个星球,输入每个星球一天的时间,日出和日落的时间。从日落到日出(包括日出、日落)是黑夜。其他的为白天。问在前1825天里能不能有一个时辰满足所有的星球都是夜晚。

直接模拟

 1 #include
 2 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 }
View Code

 

B题:Breaking Biscuits

给出一个二维多边形按逆时针方向的坐标,让该多边形的某一方向能放在一个长方形里,求该长方形的最小宽度。

根据给出的点建立凸包,然后枚举凸包的每条边,计算凸包的其他点到该边的最大值,然后再找到这些最大值的最小值

 1 #include 
 2 
 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.xb.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;j1;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;i1;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 }
View Code

 

C题:Cued In

直接模拟

 1 #include
 2 
 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 }
View Code

 

D题:Deranging Hat

直接按照题目意思做

 1 #include
 2 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 }
View Code

  

E题:Education

该题与原题输出不同,请注意!

对于该题来说,直接写。

 1 #include 
 2  
 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 }
View Code

 

F题:Flipping Coins

 1 #include
 2 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 }
View Code

 

I题:I Work All Day

求能产生最大余数的那个数

 1 #include 
 2  
 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 }
View Code

 

J题:Just A Minim

直接按照题意写

 1 #include
 2  
 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 }
View Code

 

L题:Lounge Lizards

给出电视机的坐标,有n个人,分别输入他们的坐标和高度,可以把某些人赶出去,问最多能有多少人能看到电视

首先求出每个人与电视机的方向向量,并约分,然后对于每组求LIS,最后取和

 1 #include 
 2 
 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; ij)
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 }
View Code

 

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 #include
  2 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 }
View Code

 

转载于:https://www.cnblogs.com/scott527407973/p/9550280.html

你可能感兴趣的:(UPC2018组队训练赛第六场)