• 2017ACM/ICPC亚洲区沈阳站(部分解题报告)


    HDU 6225 Little Boxes

    题意

    计算四个整数的和

    解题思路

    使用Java大整数

     1 import java.math.BigInteger;
     2 import java.util.Scanner;
     3 
     4 /**
     5  *
     6  * @author reqaw
     7  */
     8 public class Main {
     9 
    10     /**
    11      * @param args the command line arguments
    12      */
    13     public static void main(String[] args) {
    14         Scanner in = new Scanner(System.in);
    15         int T;
    16         T = in.nextInt();
    17         while(T-- > 0) {
    18             BigInteger a = in.nextBigInteger();
    19             BigInteger b = in.nextBigInteger();
    20             BigInteger c = in.nextBigInteger();
    21             BigInteger d = in.nextBigInteger();
    22             System.out.println(a.add(b).add(c).add(d));
    23         }
    24     }
    25     
    26 }

     HDU 6227 Rabbits

    题意

    n只兔子排在一条直线上,每只兔子都有一个坐标,最外边的兔子可以跳到两只兔子中间的空位上,每跳一次称为一次计数,问最多能够玩几次。

    解题思路

    从第二只兔子开始计算相邻的空位有几个,正着一遍,倒着一遍,取最大值即可。

     1 #include <cstdio>
     2 
     3 const int maxn = 500 + 10;
     4 int a[maxn];
     5 int main()
     6 {
     7     int T, n;
     8     scanf("%d", &T);
     9     while(T--) {
    10         scanf("%d", &n);
    11         for(int i = 0; i < n; i++) {
    12             scanf("%d", &a[i]);
    13         }
    14         int s1 = 0;
    15         for(int i = 1; i < n - 1; i++) {
    16             s1 += a[i + 1] - a[i] - 1;
    17         }
    18         int s2 = 0;
    19         for(int i = n - 2; i > 0; i--) {
    20             s2 += a[i] - a[i - 1] - 1;
    21         }
    22         printf("%d
    ", s1 > s2 ? s1 : s2);
    23     }
    24     return 0;
    25 }

     HDU 6222 Heron and His Triangle

    题意

    先定义了一个H三角形,它的三条边由连续的三个整数构成,即t-1, t , t+1,并且它的面积是一个整数。给出一个整数n(最大可能是10^30),问满足t>=n的最小t是多少。

    解题思路

    先暴力打出前几个满足条件的t,仔细观察发现满足一个规律,res[i] = res[i - 1] * 4 - res[i - 2];由于数字很大,使用Java大数。

     1 /*先暴力出前几项*/
     2 #include <cstdio>
     3 #include <cmath>
     4 typedef unsigned long long ull;
     5 int main()
     6 {
     7     for(ull t = 4; t <= 1000000; t++) {
     8         ull a = t - 1;
     9         ull b = t;
    10         ull c = t + 1;
    11         ull p = (a + b + c) / 2;
    12         ull k = p * (p - a) * (p - b) * (p - c);
    13         if((ull)sqrt(k) * (ull)sqrt(k) == k) {
    14             printf("%lld
    ", t);
    15         }
    16     }
    17     return 0;
    18 }

    找到规律后打表

     1 import java.math.BigInteger;
     2 import java.util.Scanner;
     3 
     4 /**
     5  *
     6  * @author reqaw
     7  */
     8 public class Main {
     9 
    10     /**
    11      * @param args the command line arguments
    12      */
    13     public static void main(String[] args) {
    14         BigInteger res[] = new BigInteger[100];
    15         res[0] = BigInteger.valueOf(4L);
    16         res[1] = BigInteger.valueOf(14L);
    17         for(int i = 2; i < 100; i++) {
    18             res[i] = res[i - 1].multiply(res[0]).subtract(res[i - 2]);
    19             //System.out.println(res[i]);
    20         }
    21         Scanner cin = new Scanner(System.in);
    22         int T = cin.nextInt();
    23         while(T-- > 0) {
    24             BigInteger n = cin.nextBigInteger();
    25             for(int i = 0; i < 100; i++) {
    26                 if(res[i].compareTo(n) >= 0) {
    27                     System.out.println(res[i]);
    28                     break;
    29                 }
    30             }
    31         }
    32     }
    33 
    34 }

     HDU 6219 Empty Convex Polygons

    题意

    给出n个点,求由这n个点组成的最大空凸包的面积是多少。

    解题思路

    使用求解最大空凸包的模板,基本思想是穷举所 要求解的空凸包的最低最左点(先保证最低,再保证最左)。

      对于每一个穷举到的点v,进行动态规划,用opt[i][j]表示符合如下限制的凸包中的最大面积:

      在凸包上v顺时针过来第一个点是i,并且i顺时针过来第一个点k不在i->j的左手域(k 可以等于 j)。

      1 #include <cstdio>
      2 #include <cmath>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 const int maxn = 100;
      7 const double zero = 1e-8;
      8 
      9 struct Vector {
     10     double x, y;
     11 };
     12 
     13 inline Vector operator - (Vector a, Vector b) {
     14     Vector c;
     15     c.x = a.x - b.x;
     16     c.y = a.y - b.y;
     17     return c;
     18 }
     19 inline double Sqr(double a) {
     20     return a * a;
     21 }
     22 inline int Sign(double a) {
     23     if(fabs(a) <= zero)    return 0;
     24     return a < 0 ? -1 : 1;
     25 }
     26 inline bool operator < (Vector a, Vector b) {
     27     return Sign(b.y - a.y) > 0 || Sign(b.y - a.y) == 0 && Sign(b.x - a.x) > 0;
     28 }
     29 inline double Max(double a, double b) {
     30     return a > b ? a : b;
     31 }
     32 inline double Length(Vector a) {
     33     return sqrt(Sqr(a.x) + Sqr(a.y));
     34 }
     35 inline double Cross(Vector a, Vector b) {
     36     return a.x * b.y - a.y * b.x;
     37 }
     38 
     39 Vector dot[maxn], List[maxn];
     40 double opt[maxn][maxn];
     41 int seq[maxn];
     42 int n, len;
     43 double ans;
     44 
     45 bool Compare(Vector a, Vector b) {
     46     int temp = Sign(Cross(a, b));
     47     if(temp != 0) return temp > 0;
     48     temp = Sign(Length(b) - Length(a));
     49     return temp > 0;
     50 }
     51 
     52 void Solve(int vv) {
     53     int t, i, j, _len;
     54     for(i = len = 0; i < n; i++) {
     55         if(dot[vv] < dot[i])
     56             List[len++] = dot[i] - dot[vv];
     57     }
     58     for(i = 0; i < len; i++) {
     59         for(j = 0; j < len; j++) {
     60             opt[i][j] = 0;
     61         }
     62     }
     63     sort(List, List + len, Compare);
     64     double v;
     65     for(t = 1; t < len; t++) {
     66         _len = 0;
     67         for(i = t - 1; i >= 0 && Sign(Cross(List[t], List[i])) == 0; i--);
     68          
     69         while(i >= 0) {
     70             v = Cross(List[i], List[t]) / 2;
     71             seq[_len++] = i;
     72             for(j = i - 1; j >= 0 && Sign(Cross(List[i] - List[t], 
     73             List[j] - List[t])) > 0; j--);
     74             if(j >= 0)
     75                 v += opt[i][j];    
     76             ans = Max(ans, v);
     77             opt[t][i] = v;
     78             i = j;
     79         }
     80         for(i = _len - 2; i >= 0; i--) {
     81             opt[t][seq[i]] = Max(opt[t][seq[i]], opt[t][seq[i + 1]]);
     82         }
     83     }
     84 }
     85 
     86 int i;
     87 double Empty() {
     88     ans = 0;
     89     for(i = 0; i < n; i++) {
     90         Solve(i);
     91     }
     92     return ans;
     93 }
     94 
     95 int main()
     96 {
     97     int T;
     98     scanf("%d", &T);
     99     while(T--) {
    100         scanf("%d", &n);
    101         for(i = 0; i < n; i++) {
    102             scanf("%lf%lf", &dot[i].x, &dot[i].y);
    103         }    
    104         printf("%.1lf
    ", Empty()); 
    105     }
    106     return 0;
    107 }

    HDU 6228 Tree

    题意

    相对题意不太好理解,给出n个顶点的无根树,也即无向图,k种颜色,问将每一个顶点染成一种颜色,然后将同种颜色的顶点用最少的边连起来(以及每两点间是最短路)组成E,有k中颜色,也就是每一种染色方案有E1,E2...Ek,问它们的交集(边的交集)最大是多少

    解题思路

    关键是题意的转化,可以想象的是在一个无根树中,给每个点染上k种颜色中的一种,然后将颜色相同的点使用最短路连接起来,连接起来的边算刷一遍,最后求的就是所有的边中,次数被刷k次及其以上的边最多有多少条。

    具体实现时,先明白如果该边满足条件,那么两端的点都需要大于k个才行,我们使用深搜计算每个节点的子孙数即可。

     1 #include <cstdio>
     2 #include <vector>
     3 using namespace std;
     4 
     5 const int maxn = 200000 + 10;
     6 int n, k;
     7 int ans;
     8 vector<int> e[maxn];
     9 int num[maxn];
    10 
    11 void dfs(int u, int pre) {
    12     num[u] = 1;
    13     int eus = e[u].size();
    14     for(int i = 0; i < eus; i++) {
    15         int v = e[u][i];
    16         if(v == pre)    continue;
    17         dfs(v, u);
    18         
    19         num[u] += num[v];//递归返回时将u的子孙结点数加上 
    20         if(num[v] >= k && n - num[v] >= k)    ans++;
    21     }    
    22 }
    23 
    24 int main()
    25 {
    26     int T;
    27     scanf("%d", &T);
    28     while(T--) {
    29         scanf("%d%d", &n, &k);
    30         for(int i = 0; i < maxn; i++) {
    31             e[i].clear();
    32         }
    33         for(int i = 0; i < n - 1; i++) {
    34             int u, v;
    35             scanf("%d%d", &u, &v);
    36             e[u].push_back(v);
    37             e[v].push_back(u);            
    38         }
    39         ans = 0;
    40         dfs(1, -1);
    41         printf("%d
    ", ans);
    42     }    
    43     return 0;
    44 }
  • 相关阅读:
    互联网预言大神:凯文·凯利——预测未来的12个趋势
    仅有算法远远不够:AI突破下一站,需要对硬件重新审视
    软件开发中经常使用的5种设计模式
    强化学习到底是什么,它如何运作?
    2020年网络安全的六大经验教训
    选择困难终结者:不同问题之下的机器学习算法
    为什么物联网如此重要?
    Pku3080 Blue Jeans
    pku1734 Musical Theme
    [Usaco2006 Dec]Milk Patterns
  • 原文地址:https://www.cnblogs.com/wenzhixin/p/9794497.html
Copyright © 2020-2023  润新知