2015 Multi-University Training Contest 2

时间:2021-06-02 04:27:52

1001 Angry Trees

 

1002 Buildings

比赛的时候没看懂题。看完题解依旧WA好久。
偷看数据发现坑多。不容易考虑全。

假设m>=n,否则转置一下。
下面所描述的left,right,up,down全部和官方题解相同。
要注意。left,right与up,down在图上的取法是不一样的。
 
首先考虑无坏点的情况。取ans=n/2+1必然能覆盖整个图。此时全部纵向铺条。
2015 Multi-University Training Contest 2
如图所示为n=4,m=5的情况。
 
 
2015 Multi-University Training Contest 2
加上坏点后。要分两类讨论。
 
i) 当min(left,right)<=ans时。不妨设left<ans。

那么只要坏点左边(包含坏点)横向铺条。右边纵向铺条。一定能铺满。

2015 Multi-University Training Contest 2
如图所示为n=5,m=9,x=3,y=3的情况。


ii)当min(left,right)>ans时。我们需要进一步讨论 。


①如果坏点在x方向上处于中间位置(n为奇数时的x=n/2+1,n为偶数时的x=n/2或x=n/2+1)那么用长度为ans纵向铺条仍然可以。

2015 Multi-University Training Contest 2
如图分别为n=5,m=7,x=3,y=4与n=6,m=9,x=3,y=5的情况。


②如果x不在中间位置。 那么长度为ans的条已经无法覆盖全图了。(无论横铺还是纵铺。)

2015 Multi-University Training Contest 2
如图分别为n=5,m=7,x=1,y=4与n=6,m=9,x=1,y=5的情况。
红色表示无法覆盖的区域。

 

此时我们有两种方案(不妨设ans<left<=right)
1)在坏点左边(包含坏点)用 left长度横铺,右边(不包含坏点)纵铺。(因为left>ans。这是必然可行的。)
2)用max(up,down) 长度全部纵铺。
那么在1)与2)中选择更优的即为答案。

2015 Multi-University Training Contest 2
在n=5,m=7,x=1,y=4与n=6,m=9,x=1,y=5的情况下
方案1)与2)是相同的,两者均可。

 

2015 Multi-University Training Contest 2
如果考虑n=6,m=9,x=2,y=5的情况。那么显然方案2)更优。

 

最后一个坑。边长为奇数的方形且坏点在中间。答案为ans-1。

2015 Multi-University Training Contest 2
如图为n=5,m=5,x=3,y=3的情况。

2015 Multi-University Training Contest 22015 Multi-University Training Contest 2
 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 
 6 int main(void)
 7 {
 8     int n,m,x,y;
 9     while((scanf("%d%d%d%d",&n,&m,&x,&y))!=EOF)
10     {
11         if(n>m) {swap(n,m); swap(x,y);}
12         int ans=(n+1)/2;
13         int left=y,right=m-y+1,up=x-1,down=n-x;
14         if(min(left,right)>ans&&max(up,down)-min(up,down)>1)
15             ans=min(min(left,right),max(up,down));
16         if(n%2&&m==n&&left==right&&up==down) ans--;
17         printf("%d\n",ans);
18     }
19     return 0;
20 }
Aguin

 

1003  Connect the Graph

 

1004 Delicious Apples

苹果数最多为1e5。所以把每个苹果看成一个点。

按中线将苹果分成左右两边。用dist表示每个苹果的距离。

cnt计两边苹果数。全部读好sort一遍。

先考虑贪心的取两边的苹果。

sum[i]表示在某一边取完1-i的苹果回去后走的最小路程。

递推sum数组直到sum[cnt]。

转移方程是i<=k时sum[i]=2*dist[i],i>k时sum[i]=sum[i-k]+2*dist[i]。

这样的话得到一个ans=suml[cntl]+sumr[cntr]。

然而会发现。如果贪心到最后在一边取的苹果不到k个。那么会存在走一圈更优的情况。

但是走一圈最多只有一次。因为如果多于一次就能拆成两个小于半圈的。必然小于一圈。

那么我们可以枚举走一圈的时候。分别在左半右半取了多少个。

例如左半取i个右半取k-i个。那么这i个一定要取左半距离最大的。右半同理。

这里要注意枚举时,枚举的个数不能超过左边和右边的总个数。

最后注意LL。

2015 Multi-University Training Contest 22015 Multi-University Training Contest 2
 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 # define maxn 100010
 7 int distl[maxn],distr[maxn];
 8 LL suml[maxn]={0},sumr[maxn]={0};
 9 
10 int main(void)
11 {
12     int T; cin>>T;
13     while(T--)
14     {
15         LL L; int n,k;
16         scanf("%I64d%d%d",&L,&n,&k);
17         int cntl=0,cntr=0;
18         for(int i=1;i<=n;i++)
19         {
20             int x,a; scanf("%d%d",&x,&a);
21             for(int j=0;j<a;j++)
22             {
23                 if(2*x<L) distl[++cntl]=x;
24                 else distr[++cntr]=L-x;
25             }
26         }
27         sort(distl+1,distl+1+cntl);
28         sort(distr+1,distr+1+cntr);
29         for(int i=1;i<=cntl;i++)
30         {
31             if(i<=k) suml[i]=2*distl[i];
32             else suml[i]=suml[i-k]+2*distl[i];
33         }
34         for(int i=1;i<=cntr;i++)
35         {
36             if(i<=k) sumr[i]=2*distr[i];
37             else sumr[i]=sumr[i-k]+2*distr[i];
38         }
39         LL ans=suml[cntl]+sumr[cntr];
40         for(int i=0;i<=k;i++)
41         {
42             int posl=max(0,cntl-(k-i));
43             int posr=max(0,cntr-i);
44             ans=min(ans,L+suml[posl]+sumr[posr]);
45         }
46         printf("%I64d\n",ans);
47     }
48     return 0;
49 }
Aguin

 

1005 Eastest Magical Day Seep Group's Summer

 

1006 Friends

连个暴搜都写不出来。不开心。

官方题解说搜点。加上两点优化:1.只考虑偶数边 2.最后一条边由前面的边确定。

在网上找到了简单易懂的做法。跑的不是很快是超级快。

先读边。每个点记下度数。如果有奇数的就直接输0过了。

所有点的度都是偶数的情况下。每个节点的on边与off边是相等的,即为度数一半。

直接搜边。枚举每条边分别是on边与off边的情况。

如果过程中有点的on边或者off边举完了。边还没搜完。

那么该情况就是不可行的。直接return。

2015 Multi-University Training Contest 22015 Multi-University Training Contest 2
 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 # define CLR(x) memset(x,0,sizeof(x))
 6 int ans,m,n,deg[10],on[10],off[10];
 7 
 8 struct E
 9 {
10     int from,to;
11 } edge[30];
12 
13 void dfs(int x)
14 {
15     if(x>m) {ans++; return;}
16     int u=edge[x].from,v=edge[x].to;
17     if(on[u]&&on[v])
18     {
19         on[u]--; on[v]--;
20         dfs(x+1);
21         on[u]++; on[v]++;
22     }
23     if(off[u]&&off[v])
24     {
25         off[u]--; off[v]--;
26         dfs(x+1);
27         off[u]++; off[v]++;
28     }
29     return;
30 }
31 
32 int main(void)
33 {
34     int T; cin>>T;
35     while(T--)
36     {
37         CLR(edge); CLR(deg); CLR(on); CLR(off);
38         scanf("%d%d",&n,&m);
39         for(int i=1;i<=m;i++)
40         {
41             int u,v; scanf("%d%d",&u,&v);
42             edge[i].from=u; edge[i].to=v;
43             deg[u]++; deg[v]++;
44         }
45         int ok=1;
46         for(int i=1;i<=n;i++) if(deg[i]%2) {ok=0; break;}
47         if(!ok) {printf("0\n"); continue;}
48         for(int i=1;i<=n;i++) on[i]=off[i]=deg[i]/2;
49         ans=0; dfs(1);
50         printf("%d\n",ans);
51     }
52     return 0;
53 }
Aguin

 

1007 Gorgeous Sequence

 

1008 He is Flying

 

1009 I Wanna Become A 24-Point Master

没什么技术含量。看官方题解。

只要能推出所有的情况就好。

然而把式子全部变成代码也挺不容易的。

一处WA整个都要重新检查一次。过的时候真的感动哭。

【第一次遇见说代码太长的情况。也有可能是HDU或者我网炸。】

2015 Multi-University Training Contest 22015 Multi-University Training Contest 2
 1 # include <iostream>
 2 # include <cstdio>
 3 using namespace std;
 4 
 5 int main(void)
 6 {
 7     int n;
 8     while((scanf("%d",&n))!=EOF)
 9     {
10         if(n<4) printf("-1\n");
11         if(n==4) printf("1 * 2\n5 + 3\n6 + 4\n");
12         if(n==5) printf("1 / 2\n6 / 3\n4 - 7\n5 * 8\n");
13         if(n==6) printf("1 + 2\n3 + 7\n4 + 8\n5 + 9\n10 - 6\n");
14         if(n==7) printf("1 * 2\n3 / 4\n5 + 6\n8 - 9\n11 / 10\n12 * 7\n");
15         if(n==8) 
16         {
17             printf("1 + 2\n9 + 3\n4 - 5\n11 * 6\n");
18             printf("12 * 7\n13 * 8\n14 + 10\n");
19         }
20         if(n==9)
21         {
22             printf("1 + 2\n10 + 3\n4 / 5\n6 / 7\n");
23             printf("8 / 9\n11 - 12\n15 - 13\n16 - 14\n");
24         }
25         if(n==10)
26         {
27             printf("1 / 2\n3 / 4\n5 / 6\n7 / 8\n9 + 10\n");
28             printf("11 + 12\n16 + 13\n17 + 14\n18 + 15\n");
29         }
30         if(n==11)
31         {
32             printf("1 + 2\n3 / 4\n5 / 6\n12 + 13\n15 + 14\n");
33             printf("7 - 8\n17 * 9\n18 * 10\n19 * 11\n20 + 16\n");
34         }
35         if(n==12)
36         {
37             printf("1 - 2\n");
38             for(int i=0;i<8;i++) printf("%d * %d\n",i+3,i+13);
39             printf("11 + 12\n21 + 22\n");
40         }
41         if(n==13)
42         {
43             printf("1 / 2\n3 - 14\n4 + 5\n16 / 6\n15 * 17\n7 - 8\n");
44             for(int i=0;i<5;i++) printf("%d * %d\n",i+9,i+19);
45             printf("24 + 18\n");
46         }
47         if(n==14)
48         {
49             printf("1 / 2\n3 / 4\n5 - 15\n17 - 16\n6 + 7\n19 / 8\n20 * 18\n9 - 10\n");
50             for(int i=0;i<4;i++) printf("%d * %d\n",i+11,i+22);
51             printf("21 + 26\n");
52         }
53         if(n>14)
54         {
55             printf("1 + 2\n3 + 4\n5 + 6\n7 + 8\n%d + 9\n",n+1);
56             for(int i=0;i<4;i++) printf("%d / %d\n",n+2+i,i+10);
57             printf("14 - 15\n");
58             for(int i=0;i<n-15;i++) printf("%d * %d\n",i+16,n+10+i);
59             printf("%d + %d\n%d * %d\n%d * %d\n%d * %d\n",2*n-5,n+6,2*n-4,n+7,2*n-3,n+8,2*n-2,n+9);
60         }
61     }
62     return 0;
63 }
Aguin

 

1010 JRY is Fighting