• [考试]20151010


    1、前言

    又是绿书上的题目。这种画风感觉还是好些的,虽然都是远古时代的。今天题目感觉难度适中,但是太过于偏向动态规划了吧。。。还有搜索傻逼题乱入。

    2、Sort 产品排序

    大概题意:给出n个产品,每个产品有加工时间和冷却时间。现有两台加工机,每台加工机同一时间只能加工一个产品。产品加工完后就进入冷却时间。要求在尽可能短的时间内完成所有产品的所有工序,求最短时间。

    题解:

      动态规划。设存在两个产品x和y,y的冷却时间大于x,且x排在y之前。如果x和y是相邻的,可以发现在这种情况下完成时间是max{xa+xb,xa+ya+yb}=xa+ya+yb;如果x排在y之后,则完成时间是max{ya+yb,xa+ya+xb}<=xa+ya+yb,所以y在x前面一定不会劣于x在y前面。所以我们按照b排降序,一定能找到最优解。

      设f[i][j]表示前i个产品,其中第一个机器上的加工时间之和为j时的最优解,s[i]=a[j](j∈[1,j])。状态转移方程:f[i][j]=min{max{f[i-1][j-a[i].x],j+a[i].y},max{f[i-1][j],s[i]-j+a[i].y}},分别表示放入机器1还是机器2。

    3、Ball 分球

    大概题意:将n个有标号的球放入m个没有区别的盒子中,每个盒子至少有一个球,求方案数。

    总结:我不管是什么第二类斯特林数云云。。。反正我又是找规律发现出来的。

    题解:

      动态规划第二弹。设f[i][j]表示将前i个球放入j个盒子中的方案数,f[i][j]=f[i-1][j-1]+f[i-1][j]*j。计算的时候要高精度加乘法。

    4、Map 地图

    大概题意:在一个n*m的0-1矩阵,求1的极大连通块个数。

    题解:

      搜索傻逼题乱入一大堆动态规划题目中。

    5、Polygon 坐标变换

    大概题意:给定平面中n个点,求一个凸包,使得凸包的顶点含给定的点最多。凸包边上不能有给定点,且原点必须在凸包上。

    总结:这道题看上去是计算几何的题目,但是在求解过程中,计算几何的成分并不是很多。我试着直接用求凸包的方式去求,但是被卡在了共线的问题上。

    题解:

      因为要选尽量多的点,我们同样地可以考虑用动态规划去取最优解。状态比较特殊,每次的状态都是以边为主体,f[i][j]表示当前选择了(i,j)这条边所求得的最多的边数。首先初始状态显然i=1,最后求得答案的状态显然j=1。因为点数不多,我们可以根据当前的边,然后选择其他所有没有选的点,首先判断是否满足凸包的要求(利用叉积判断这个点在当前线的左侧还是右侧),然后再找到最佳的点。

      所以说从头到尾真正和计算几何有紧密联系的地方就是一个计算整数叉积的地方,其他的部分就是最简单的动态规划。

    代码:

    ------------------------------------------------------------------------------------------------------

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #define MAXN 105
    using namespace std;

     

    struct Node { int x, y; } a[MAXN];

     

    bool x(Node a, Node b) { return a.y * b.x < b.y * a.x; }

     

    int calc(int x1, int y1, int x2, int y2) { return x1 * y2 - x2 * y1; }

     

    int n, f[MAXN][MAXN], ans;

     

    int main()
    {
      freopen("polygon.in", "r", stdin);
      freopen("polygon.out", "w", stdout);
      scanf("%d", &n); n++, a[1].x = a[1].y = 0;
      for (int i = 2; i <= n; i++) scanf("%d %d", &a[i].x, &a[i].y);
      sort(a + 2, a + n + 1, x);
      for (int i = 2; i <= n; i++) f[1][i] = 1;
      for (int i = 2; i <= n; i++)
        for (int j = i + 1; j <= n + 1; j++)
        {
          int l = j == n + 1 ? 1 : j;
          for (int k = 1; k < i; k++)
            if (calc(a[k].x - a[i].x, a[k].y - a[i].y, a[l].x - a[i].x, a[l].y - a[i].y) < 0)
          f[i][l] = max(f[i][l], f[k][i] + 1);
        }
      for (int i = 2; i <= n; i++) ans = max(ans, f[i][1]);
      printf("%d", ans);
      return 0;
    }

    ------------------------------------------------------------------------------------------------------

  • 相关阅读:
    杂项
    导出查询数据(大数据量)
    设置现有字段自增
    C++ 矩形交集和并集的面积-离散化
    Python使用flask架构、跨域
    匈牙利命名法
    C++ main函数
    windows编译boost
    mfc HackerTools监控键盘按键
    mfc HackerTools远程线程注入
  • 原文地址:https://www.cnblogs.com/jinkun113/p/4868276.html
Copyright © 2020-2023  润新知