zoukankan      html  css  js  c++  java
  • 2015 Multi-University Training Contest 2

    1001 Angry Trees

    1002 Buildings

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

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

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


    如图所示为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纵向铺条仍然可以。


    如图分别为n=5,m=7,x=3,y=4与n=6,m=9,x=3,y=5的情况。


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


    如图分别为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)中选择更优的即为答案。


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


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

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


    如图为n=5,m=5,x=3,y=3的情况。

     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
    ",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。

     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
    ",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。

     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
    "); continue;}
    48         for(int i=1;i<=n;i++) on[i]=off[i]=deg[i]/2;
    49         ans=0; dfs(1);
    50         printf("%d
    ",ans);
    51     }
    52     return 0;
    53 }
    Aguin

    1007 Gorgeous Sequence

    1008 He is Flying

    1009 I Wanna Become A 24-Point Master

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

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

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

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

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

     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
    ");
    11         if(n==4) printf("1 * 2
    5 + 3
    6 + 4
    ");
    12         if(n==5) printf("1 / 2
    6 / 3
    4 - 7
    5 * 8
    ");
    13         if(n==6) printf("1 + 2
    3 + 7
    4 + 8
    5 + 9
    10 - 6
    ");
    14         if(n==7) printf("1 * 2
    3 / 4
    5 + 6
    8 - 9
    11 / 10
    12 * 7
    ");
    15         if(n==8) 
    16         {
    17             printf("1 + 2
    9 + 3
    4 - 5
    11 * 6
    ");
    18             printf("12 * 7
    13 * 8
    14 + 10
    ");
    19         }
    20         if(n==9)
    21         {
    22             printf("1 + 2
    10 + 3
    4 / 5
    6 / 7
    ");
    23             printf("8 / 9
    11 - 12
    15 - 13
    16 - 14
    ");
    24         }
    25         if(n==10)
    26         {
    27             printf("1 / 2
    3 / 4
    5 / 6
    7 / 8
    9 + 10
    ");
    28             printf("11 + 12
    16 + 13
    17 + 14
    18 + 15
    ");
    29         }
    30         if(n==11)
    31         {
    32             printf("1 + 2
    3 / 4
    5 / 6
    12 + 13
    15 + 14
    ");
    33             printf("7 - 8
    17 * 9
    18 * 10
    19 * 11
    20 + 16
    ");
    34         }
    35         if(n==12)
    36         {
    37             printf("1 - 2
    ");
    38             for(int i=0;i<8;i++) printf("%d * %d
    ",i+3,i+13);
    39             printf("11 + 12
    21 + 22
    ");
    40         }
    41         if(n==13)
    42         {
    43             printf("1 / 2
    3 - 14
    4 + 5
    16 / 6
    15 * 17
    7 - 8
    ");
    44             for(int i=0;i<5;i++) printf("%d * %d
    ",i+9,i+19);
    45             printf("24 + 18
    ");
    46         }
    47         if(n==14)
    48         {
    49             printf("1 / 2
    3 / 4
    5 - 15
    17 - 16
    6 + 7
    19 / 8
    20 * 18
    9 - 10
    ");
    50             for(int i=0;i<4;i++) printf("%d * %d
    ",i+11,i+22);
    51             printf("21 + 26
    ");
    52         }
    53         if(n>14)
    54         {
    55             printf("1 + 2
    3 + 4
    5 + 6
    7 + 8
    %d + 9
    ",n+1);
    56             for(int i=0;i<4;i++) printf("%d / %d
    ",n+2+i,i+10);
    57             printf("14 - 15
    ");
    58             for(int i=0;i<n-15;i++) printf("%d * %d
    ",i+16,n+10+i);
    59             printf("%d + %d
    %d * %d
    %d * %d
    %d * %d
    ",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

  • 相关阅读:
    [论文泛读]Web服务综述相关论文1(1篇)
    [论文泛读]QoS of Web service 综述相关论文1(1篇)
    用jquery判断一个对象是否存在
    android 程序开发 R.### cannot be resolved
    发票管理及打印系统的部分代码
    项目下R.java竟然没有R.id这个类!
    C#调用ISAG网关下发彩信长征路上的一个小脚印
    机打发票打印管理
    Android获取手机和系统版本等信息的代码
    Android开发环境搭建全程演示(jdk+eclipse+android sdk)
  • 原文地址:https://www.cnblogs.com/Aguin/p/4671330.html
Copyright © 2011-2022 走看看