• 2015 Multi-University Training Contest 2


    多校第二场,赛后总共做出四题,总结的有点晚了,太懒,下面给出解题报告!!

    Hdu 5301 Buildings

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5301

    题意:有块地为n*m列的矩阵,要建造矩形公寓来完全覆盖这块地((x,y)方格除外)
      且每个公寓必须有一边在这块地的矩阵的边缘上。
      求满足条件的方案中公寓最大面积的最小值。

    思路:相当于用矩形填充n*m的矩阵,且矩形至少有一条边在该矩阵的边界上
      若不考虑(x,y)方格被删除,ans=(min(m,n)+1)/2;
      删除(x,y)后,若 m=n且n为奇数,且(x,y)在中心点,ans=ans-1;
      否则 如图:

      与(x,y)上下左右相邻点,只能往三个方向建公寓,对于这四个点
      分别取对应的三个方向建公寓的最小面积s=min(s1,s2,s3);
      ans=max(ans,s);

    参考代码:

      

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #define INF 999999999
     4 const int dirX[4]={0,0,-1,1};
     5 const int dirY[4]={1,-1,0,0};
     6 using namespace std;
     7 int main()
     8 {
     9     int n,m,x,y;
    10     while(scanf("%d%d%d%d",&n,&m,&x,&y)!=EOF){
    11         int ans=(min(m,n)+1)/2;
    12         if(n%2&&m==n&&x==y&&x==(n+1)/2){
    13             printf("%d
    ",ans-1);
    14             continue;
    15         }
    16         for(int i=0;i<4;i++){
    17             int row=x+dirX[i];
    18             int col=y+dirY[i];
    19             int temp=INF;
    20             if(row>=1&&row<=n&&col>=1&&col<=m){
    21                 if(row-1!=x)
    22                     temp=min(temp,row);
    23                 if(row+1!=x)
    24                     temp=min(temp,n-row+1);
    25                 if(col-1!=y)
    26                     temp=min(temp,col);
    27                 if(col+1!=y)
    28                     temp=min(temp,m-col+1);
    29                 ans=max(ans,temp);
    30             }
    31         }
    32         printf("%d
    ",ans);
    33     }
    34     return 0;
    35 }
    View Code

    Hdu 5303 Delicious Apples

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5303

    题意:一个环形道上有n个苹果树,第i棵树与仓库的顺时针距离为xi,树上有ai个苹果,仓库在位置0
      你有一个容量为k的篮子,要从仓库出发去摘苹果,篮子装满后要回到起点清空篮子,
      问你从起点出发,摘完所有苹果所走的最短路程。

    思路:从起点可以顺时针或逆时针出发,最后的结果肯定是
      顺时针取一定的苹果所走的最短路与逆时针走的最短路的和。

      对于每棵树上的苹果,肯定是能现整取的先取完,然后回到原点,预处理一下,然后每棵树的苹果数就是原来的苹果数%k;

      对于剩下的每个苹果离散化,每个苹果自成一个分量,

      用sl表示左半圈苹果总数,用sr表示右半圈苹果总数。

      用pl[]表示左半圈各个苹果距离远点的最短距离,pr[]表示右半圈苹果距离远点的最短距离。

      用dpl[i]表示取左半圈的第i个苹果要走的最短路径,同理dpr[i]表示取右半圈的第i个苹果要走的最短路径。

      ans=(dpl[sl-1]+dpr[sr-1])*2;//左边的都往左边运,右边的都往右边运得到的路程总和。

      因为最多存在走一圈比分别走两边的短的情况,所以枚举每一个走全圈的情况,和ans比较大小,取小的那个;

    参考代码:

       

      1 #include<stdio.h>
      2 #include<algorithm>
      3 #include<string.h>
      4 using namespace std;
      5 struct node
      6 {
      7     long long dis,x;
      8 } left[100001],right[100001];
      9 long long pl[100001],pr[100001];
     10 long long dpl[100001],dpr[100001];
     11 int cmp(node x,node y)
     12 {
     13     return x.dis<y.dis;
     14 }
     15 int main()
     16 {
     17     int T;
     18     int L,n,k;
     19     long long sum;
     20     long long ans;
     21     scanf("%d",&T);
     22     while(T--)
     23     {
     24         sum=0;
     25         long long a,b;
     26         int l=0,r=0;
     27         scanf("%d%d%d",&L,&n,&k);
     28         memset(pl,0,sizeof(pl));
     29         memset(pr,0,sizeof(pr));
     30         memset(dpl,0,sizeof(dpl));
     31         memset(dpr,0,sizeof(dpr));
     32         for(int i=0; i<n; i++)
     33         {
     34             scanf("%I64d%I64d",&a,&b);
     35             if(a*2<=L)
     36             {
     37                 left[l].dis=a;
     38                 left[l++].x=b;
     39             }
     40             else
     41             {
     42                 right[r].dis=L-a;
     43                 right[r++].x=b;
     44             }
     45         }
     46         sort(left,left+l,cmp);
     47         sort(right,right+r,cmp);
     48         for(int i=0; i<l; i++)
     49         {
     50             sum+=(left[i].dis)*(left[i].x/k)*2;
     51             left[i].x=left[i].x%k;
     52         }
     53         for(int i=0; i<r; i++)
     54         {
     55             sum+=(right[i].dis)*(right[i].x/k)*2;
     56             right[i].x=right[i].x%k;
     57         }
     58         //剩余的苹果离散化
     59         int sl=1;//左边苹果总数
     60         int sr=1;//右边苹果总数
     61         for(int i=0; i<l; i++)
     62         {
     63             if(left[i].x)
     64             {
     65                 for(int j=0; j<left[i].x; j++)
     66                 {
     67                     pl[sl++]=left[i].dis;
     68                 }
     69             }
     70         }
     71         for(int i=0; i<r; i++)
     72         {
     73             if(right[i].x)
     74             {
     75                 for(int j=0; j<right[i].x; j++)
     76                 {
     77                     pr[sr++]=right[i].dis;
     78                 }
     79             }
     80         }
     81         for(int i = 1; i < sl; i++)
     82         {
     83             if(i<=k)
     84                 dpl[i]=pl[i];
     85             else
     86                 dpl[i]=dpl[i-k]+pl[i];
     87         }
     88         for(int i = 1; i < sr; i++)
     89         {
     90             if(i<=k)
     91                 dpr[i]=pr[i];
     92             else
     93                 dpr[i]=dpr[i-k]+pr[i];
     94         }
     95         ans=(dpl[sl-1]+dpr[sr-1])*2;//左边的往左边运,右边的网友边运
     96         for(int i=0; i<=sl-1&&i<=k; i++)
     97         {
     98             int p1=sl-i-1;
     99             int p2=max(0,sr-1-(k - i));
    100             if(2*(dpl[p1] + dpr[p2])+L<ans)
    101                 ans=2*(dpl[p1] + dpr[p2])+L;
    102         }
    103         printf("%I64d
    ",ans+sum);
    104     }
    105     return 0;
    106 }
    View Code


    另一种方法更好理解:从起点可以顺时针或逆时针出发,最后的结果肯定是
      顺时针取一定的苹果所走的最短路与逆时针走的最短路的和。
      那么设dp[2][i],0代表顺时针,1代表逆时针,i代表取的苹果数,
      值为取完i个苹果回到原点的最短路程。x[i]为第i个苹果所在的位置。
      以顺时针为例,如果2x[i] <L,那么后来走的路程为2x[i],反之,为L;
    转移方程:
      dp[0][i] = min(dp[0][i],dp[0][i-j]+(2*x[i] <L ? 2*x[i] : L)) (1 <= j <= k)
      因为dp[0][i]是非递减的,所以优化方程:
      dp[0][i] = dp[0][i-k]+(2*x[i] <L ? 2*x[i] : L)

    参考代码:

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #define INF 0x3fffffffffffffff
     4 const int N=100010;
     5 using namespace std;
     6 struct stu{
     7     long long x,num;
     8 }app[N];
     9 long long L;
    10 int n,k,sum;
    11 long long dp[2][N];
    12 int cmp(stu a,stu b)
    13 {
    14     return a.x<b.x;
    15 }
    16 long long solve()
    17 {
    18     dp[0][0]=dp[1][0]=0;
    19     int cnt=1;
    20     for(int i=1;i<=n;i++){     //顺时针
    21         for(int j=1;j<=app[i].num;j++){
    22             int t=cnt>k?cnt-k:0;
    23             dp[0][cnt++]=dp[0][t]+min(app[i].x*2,L);
    24         }
    25     }
    26     cnt=1;
    27     for(int i=n;i>=1;i--){     //逆时针
    28         for(int j=1;j<=app[i].num;j++){
    29             int t=cnt>k?cnt-k:0;
    30             dp[1][cnt++]=dp[1][t]+min((L-app[i].x)*2,L);
    31         }
    32     }
    33     long long ans=INF;
    34     for(int i=0;i<=sum;i++)
    35         ans=min(ans,dp[0][i]+dp[1][sum-i]);
    36     return ans;
    37 }
    38 int main()
    39 {
    40     int T;
    41     scanf("%d",&T);
    42     while(T--){
    43         scanf("%I64d%d%d",&L,&n,&k);
    44         sum=0;
    45         for(int i=1;i<=n;i++){
    46             scanf("%I64d%I64d",&app[i].x,&app[i].num);
    47             sum+=app[i].num;
    48         }
    49         sort(app+1,app+n+1,cmp);
    50         long long ans=solve();
    51         printf("%I64d
    ",ans);
    52     }
    53     return 0;
    54 }
    View Code

    Hdu 5305 Friends

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5305

    题意:有n个人,m组关系,表示谁和谁是朋友关系
      朋友分为线上朋友和线下朋友,
      求满足每个人的线上朋友数和线下朋友数相同
      有多少种的情况

    思路:题中n<=8,m<=n(n-1)/2,对于每组朋友关系
      要么为线上,要么为线下,dfs加剪枝
      要保证每个人线上朋友和线下朋友人数相等,
      则每个人的朋友数都为偶数,且总边数m为偶数,否则输出0

    参考代码:

      

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<string.h>
     5 #include<stdlib.h>
     6 using namespace std;
     7 int n,m,sum;
     8 struct node
     9 {
    10     int x,y;
    11 } fri[100];
    12 int num[10];
    13 int lf[10];
    14 int rf[10];
    15 void dfs(int p)
    16 {
    17     if(p==m)
    18     {
    19         sum++;
    20         return;
    21     }
    22     int x=fri[p].x;
    23     int y=fri[p].y;
    24     if(lf[x]&&lf[y])
    25     {
    26         lf[x]--;
    27         lf[y]--;
    28         dfs(p+1);
    29         lf[x]++;
    30         lf[y]++;
    31     }
    32     if(rf[x]&&rf[y])
    33     {
    34         rf[x]--;
    35         rf[y]--;
    36         dfs(p+1);
    37         rf[x]++;
    38         rf[y]++;
    39     }
    40 }
    41 void work()
    42 {
    43     int flag=0;
    44     for(int i=1; i<=n; i++)
    45     {
    46         lf[i]=num[i]/2;
    47         rf[i]=num[i]/2;
    48         if(num[i]%2)
    49         {
    50             flag=1;
    51             break;
    52         }
    53     }
    54     if(flag)
    55     {
    56         puts("0");
    57     }
    58     else{
    59         dfs(0);
    60         printf("%d
    ",sum);
    61     }
    62 }
    63 void input()
    64 {
    65     int a,b;
    66     scanf("%d%d",&n,&m);
    67     for(int i=0; i<m; i++)
    68     {
    69         scanf("%d%d",&a,&b);
    70         fri[i].x=a;
    71         fri[i].y=b;
    72         num[a]++;
    73         num[b]++;
    74     }
    75 }
    76 int main()
    77 {
    78     int T;
    79     scanf("%d",&T);
    80     while(T--)
    81     {
    82         sum=0;
    83         memset(num,0,sizeof(num));
    84         input();
    85         work();
    86     }
    87     return 0;
    88 }
    View Code

    Hdu 5308 I Wanna Become A 24-Point Master

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5308

    题意:na1,a2an,n
      每次操作可以选两个未进行操作的数进行 “+”,”-“,”*”,”/“
      第i次操作为a b c:其中a,c为数组下标,b为操作符, 则A[n+i]=A[a] b A[c];
      要进行 n-1 次操作,使得最后数组2n-1的值为24
      需要满足的条件:每个数都有且仅能用一次(包括新生成的数)
      除法为小数除法,允许得到分数
      若能找到满足条件的操作,输出这n-1次操作,否则输出-1

    思路:

    参考代码:

      

      1 #include<stdio.h>
      2 int main()
      3 {
      4     int N;
      5     while(scanf("%d",&N)!=EOF)
      6     {
      7         if(N<=3)
      8             printf("-1
    ");
      9         else if (N == 4)
     10         {
     11             printf("1 * 2
    5 + 3
    6 + 4
    ");
     12         }
     13         else if(N == 5)
     14         {
     15             printf("1 / 2
    ");
     16             printf("6 / 3
    ");
     17             printf("4 - 7
    ");
     18             printf("5 * 8
    ");
     19         }
     20         else if(N==6)
     21         {
     22             printf("1 + 2
    ");
     23             printf("3 + 7
    ");
     24             printf("4 + 8
    ");
     25             printf("9 // 5
    ");
     26             printf("10 * 6
    ");
     27         }
     28         else if(N == 7)
     29         {
     30             printf("1 + 2
    ");
     31             printf("3 + 8
    ");
     32             printf("9 / 4
    ");
     33             printf("5 / 6
    ");
     34             printf("11 + 7
    ");
     35             printf("10 * 12
    ");
     36         }
     37         else if(N == 8)
     38         {
     39             printf("1 + 2
    ");
     40             printf("3 + 9
    ");
     41             printf("4 - 5
    ");
     42             printf("11 * 6
    ");
     43             printf("12 * 7
    ");
     44             printf("13 * 8
    ");
     45             printf("10 + 14
    ");
     46         }
     47         else if(N == 9)
     48         {
     49             printf("1 + 2
    ");
     50             printf("3 + 4
    ");
     51             printf("11 + 5
    ");
     52             printf("12 + 6
    ");
     53             printf("13 + 7
    ");
     54             printf("14 + 8
    ");
     55             printf("15 / 9
    ");
     56             printf("10 + 16
    ");
     57         }
     58         else if(N == 10)
     59         {
     60             printf("1 + 2
    ");
     61             printf("11 / 3
    ");
     62             printf("4 + 12
    ");
     63             printf("6 + 5
    ");
     64             printf("14 + 7
    ");
     65             printf("8 + 15
    ");
     66             printf("9 + 10
    ");
     67             printf("16 / 17
    ");
     68             printf("13 * 18
    ");
     69         }
     70         else if(N == 11)
     71         {
     72             printf("1 + 2
    ");
     73             printf("12 / 3
    ");
     74             printf("4 / 5
    ");
     75             printf("6 + 14
    ");
     76             printf("7 - 8
    ");
     77             printf("16 * 9
    ");
     78             printf("17 * 10
    ");
     79             printf("18 * 11
    ");
     80             printf("13 * 15
    ");
     81             printf("20 + 19
    ");
     82         }
     83         else if(N == 12)
     84         {
     85             printf("1 + 2
    ");
     86             printf("3 - 4
    ");
     87             printf("14 * 5
    ");
     88             printf("6 * 15
    ");
     89             printf("7 * 16
    ");
     90             printf("8 * 17
    ");
     91             printf("9 * 18
    ");
     92             printf("10 * 19
    ");
     93             printf("11 * 20
    ");
     94             printf("12 * 21
    ");
     95             printf("13 + 22
    ");
     96         }
     97         else
     98         {
     99             if(N%2==0)
    100             {
    101                 printf("1 + 2
    ");
    102                 int p=3,q=N+1;
    103                 for(int i=1; i<3; i++)
    104                 {
    105                     printf("%d + %d
    ",p++,q++);
    106                 }//加三次N
    107                 printf("%d / %d
    ",q++,p++);//除以N得到4
    108                 printf("%d + %d
    ",p,p+1);//得到2倍的N
    109                 int cnt1=q++;
    110                 p+=2;
    111                 for (int i=1; i<5; i++)
    112                 {
    113                     printf("%d + %d
    ",p++,q++);
    114                 }//得到6倍的N
    115                 printf("%d / %d
    ",q++,p++);//得到6
    116                 int cnt2=q++;
    117                 while (p<N)
    118                 {
    119                     printf("%d / %d
    ",p,p+1);//得到0
    120                     p+=2;
    121                     q++;
    122                     printf("%d * %d
    ",q-1,cnt1);
    123                     cnt1=q++;
    124                 }
    125                 printf("%d * %d
    ",cnt1,cnt2);//4*6=24
    126             }
    127             else
    128             {
    129                 printf("1 + 2
    ");
    130                 int p=3,q=N+1;
    131                 for (int i=1; i<2; i++)
    132                 {
    133                     printf("%d + %d
    ",p++,q++);
    134                 }
    135                 printf("%d / %d
    ",q++,p++);//得到3
    136                 printf("%d + %d
    ",p,p+1);
    137                 int cnt1=q++;
    138                 p+=2;
    139                 for (int i=1; i<7; i++)
    140                 {
    141                     printf("%d + %d
    ",p++,q++);
    142                 }
    143                 printf("%d / %d
    ",q++,p++);//得到8
    144                 int cnt2=q++;
    145                 while (p<N)
    146                 {
    147                     printf("%d / %d
    ",p,p+1);
    148                     p+=2;
    149                     q++;
    150                     printf("%d * %d
    ",q-1,cnt1);
    151                     cnt1=q++;
    152                 }
    153                 printf("%d * %d
    ",cnt1,cnt2);//3*8=24
    154             }
    155         }
    156     }
    157     return 0;
    158 }
    View Code
  • 相关阅读:
    html-Notes3
    html-Notes2 表单
    html 笔记
    网页设计常用色彩搭配表
    css
    html-Notes
    C# 输入字符串,每3个截取一次,形成一个数组
    提高情商的好书推荐 (程序猿不仅要智商也要情商)
    PHP 学习笔记---基本语法
    php学习笔记之字符串处理
  • 原文地址:https://www.cnblogs.com/PJQOOO/p/4693696.html
Copyright © 2020-2023  润新知