题意:

给出平面上n个点的坐标,选k个点,使得这k个点围起来的面积最大.

分析:

参考了 叉姐的分析不慌不忙菊苣的代码

思路我都懂,但是DP的部分还是不太会写.

我体会了一下其中含义,也许这样可能会好理解一点:

因为求出来的凸包的点数是固定的,所能选的点数也是固定的,那么不选的点的数量也是固定的.

可以反过来考虑:少选一个点,就要损失凸包上的一块面积.

假设\(d(i,j)\)表示考虑了前\(i\)个点,选了\(j\)个点,所损失的最少面积.

第\(i\)个点的前一个点是\(i'\),损失的面积为\(S_{cut}\),那么\(d(i,j)=min(d(i,j),d(i',j-1)+S_{cut})\)

最后答案就是凸包总面积减去最后损失的最小面积.

损失的面积是一小块一小块三角形累加起来的.

上个图片仅供参考:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std; typedef long long LL; const int maxn = 100 + 10; struct Point
{
LL x, y;
Point(LL x = 0, LL y = 0) : x(x), y(y) {}
void read() { scanf("%lld%lld", &x, &y); }
}; Point operator - (const Point& A, const Point& B) {
return Point(A.x - B.x, A.y - B.y);
} bool operator < (const Point& A, const Point& B) {
return A.x < B.x || (A.x == B.x && A.y < B.y);
} LL Cross(const Point& A, const Point& B) {
return A.x * B.y - A.y * B.x;
} vector<Point> p, con; vector<Point> ConvexHull() {
sort(p.begin(), p.end());
int n = p.size();
vector<Point> ch(n);
int m = 0;
for(int i = 0; i < n; i++) {
while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n - 2; i >= 0; i--) {
while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
ch.resize(m);
return ch;
} int n, k; LL d[maxn][maxn];
bool vis[maxn]; int main()
{
//freopen("in.txt", "r", stdin); int _; scanf("%d", &_);
for(int __ = 1; __ <= _; __++) {
scanf("%d%d", &n, &k);
p.resize(n);
for(int i = 0; i < n; i++) p[i].read(); con = ConvexHull();
int sz = con.size();
if(sz <= 2 || k <= 2) { printf("0\n"); continue; } LL totarea = 0;
for(int i = 2; i < sz; i++) totarea += Cross(con[i-1]-con[0], con[i] - con[0]); if(k >= sz) {
printf("%lld\n", totarea);
continue;
} LL ans = 0x3f3f3f3f3f3f3f3f;
memset(vis, false, sizeof(vis));
int times = min(10 * n / k, sz);
while(times--) {
int s = rand() % sz;
while(vis[s]) s = rand() % sz;
vis[s] = true; memset(d, 0x3f, sizeof(d));
d[0][0] = 0;
for(int i = 1; i <= sz; i++) {
int p0 = (s + i) % sz;
LL cut = 0;
for(int j = i - 1; j >= 0; j--) {
int p2 = (s + j) % sz;
int p1 = (p2 + i) % sz;
cut += Cross(con[p1] - con[p0], con[p2] - con[p0]);
for(int l = k; l > 0; l--)
d[i][l] = min(d[i][l], d[j][l-1] + cut);
}
}
ans = min(ans, d[sz][k]);
} printf("Case #%d: %lld\n", __, totarea - ans);
} return 0;
}

最新文章

  1. hdu FatMouse&#39;s Speed 动态规划DP
  2. Encrypt
  3. Android Studio 的安装和配置篇(Windows篇)
  4. HTTP 错误 404.2 - Not Found
  5. SQL全文搜索
  6. Object-C 点语法 -- 笔记
  7. 使用Project进行挣值分析
  8. 【原创】源码角度分析Android的消息机制系列(二)——ThreadLocal的工作过程
  9. SVN更新失败,提示locked 怎么破
  10. 《javascript语言精粹》读书笔记 Item1 精华与语法
  11. vue全局变量的使用
  12. Linux Apache虚拟主机配置方法
  13. Net使用RdKafka引发异常RdKafka.Internal.LibRdKafka 的类型初始值设定项引发异常
  14. [Big Data - Suro] Netflix开源数据流管理器Suro
  15. Linux下HBase和Maven的环境搭建
  16. linux:centOs7没有eth0网卡
  17. Nginx的使用(反向代理,负载均衡)
  18. 2018.07.17 洛谷P1368 工艺(最小表示法)
  19. LeetCode: 61. Rotate List(Medium)
  20. iOS工程中的info.plist文件的完整研究

热门文章

  1. final关键字,类的自动加载,命名空间
  2. mui的picker组件填坑
  3. Spring Boot自动配置原理与实践(一)
  4. filter配置多个url-pattern和排除个别servlet
  5. 【虚拟机-网络IP】保留正在使用的 VIP
  6. fpga Verilog hdl 按键消抖 部分程序讲解
  7. 洛谷 P2014 选课
  8. Python3获取大量电影信息:调用API
  9. AutoHotKey设置ide的光标功能键
  10. Integer的一个小问题