POJ2836 状态压缩dp不能逆向推倒的
来源:互联网 发布:windows.old文件夹 编辑:程序博客网 时间:2024/05/17 08:17
状态压缩DP
题意:
Description
n points are given on the Cartesian plane. Now you have to use some rectangles whose sides are parallel to the axes to cover them. Every point must be covered. And a point can be covered by several rectangles. Each rectangle should cover at least two points including those that fall on its border. Rectangles should have integral dimensions. Degenerate cases (rectangles with zero area) are not allowed. How will you choose the rectangles so as to minimize the total area of them?
Input
The input consists of several test cases. Each test cases begins with a line containing a single integer n (2 ≤ n ≤ 15). Each of the next n lines contains two integers x, y (−1,000 ≤ x, y ≤ 1,000) giving the coordinates of a point. It is assumed that no two points are the same as each other. A single zero follows the last test case.
Output
Output the minimum total area of rectangles on a separate line for each test case.
Sample Input
20 11 00
Sample Output
1
Hint
The total area is calculated by adding up the areas of rectangles used.
分析的时候自己犯了一个低级的错误,这个题目,n比较小,明显的复杂度是 n*n * 2 ^ n
先预处理出选取两个点,这两个点的面积,和所覆盖的点。
逆向分析,先给定一个状态state,然后从这个状态向前转移。
这样其实是不行的,很有意思,这个地方,如果正着考虑,那么这个集合的状态state是由前面的一个状态 or 一个集合得到的,因此,从后面不能够直接进行推导。
因此我们采用正向的思维方法,使用每一个选择的点对,去更新每个待定的状态。
其实这样还能避免了逆向思维的一个缺点,
假如,你选择了一个点对进行状态转移,那么你是将现在的状态state中的那些【i】【j】包围的点,全部剔除掉还是保留一部分?
这个需要确定,再引进2^n的复杂度,就不行了。
贴上一份个人感觉写的非常漂亮的代码:
#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;struct Rect { int area; int pset;}rect[300];int dp[1<<16];int x[20], y[20];int n;int main() { //freopen("in.txt", "r", stdin); while(scanf("%d", &n) && n) { for(int i = 0; i < n; i++) scanf("%d%d", &x[i], &y[i]); int cnt = 0; for(int i = 0; i < n-1; i++) { for(int j = i+1; j < n; j++) { rect[cnt].area = max(1, abs(x[i]-x[j]))*max(1, abs(y[i]-y[j])); rect[cnt].pset = (1<<i) | (1<<j); for(int k = 0; k < n; k++) { if((x[i]-x[k])*(x[j]-x[k]) <= 0 && (y[i]-y[k])*(y[j]-y[k]) <= 0) //判断是不是在那个矩形的范围之内 rect[cnt].pset |= 1<<k; } cnt++; } } fill(dp, dp+(1<<16), 1<<30); dp[0] = 0; for(int i = 0; i < cnt; i++) { for(int j = 0; j < 1<<n; j++) { int p = j|rect[i].pset; if(dp[j] != 1<<30 && p != j) { dp[p] = min(dp[p], dp[j]+rect[i].area); //因为有可能有很多个状态都指向这个状态,如果反向的搜索,复杂度会升高,并且有很多没有意义的搜索 } } } printf("%d\n", dp[(1<<n)-1]); } return 0;}
- POJ2836 状态压缩dp不能逆向推倒的
- poj2836(状态压缩dp)
- poj2836 状态压缩dp
- poj2836状态压缩DP+批量加入状态
- poj2836 状态压缩~矩形覆盖
- POJ2836-Rectangular Covering-状态dp
- poj1185 状态压缩的dp
- poj2836 状压dp
- poj2836(状压dp)
- POJ1739 基于连通性的状态压缩dp
- hunnu 11101 fix 状态压缩的DP
- HDU 4433 类似于状态压缩的DP
- HDU 1074 第一次的状态压缩DP
- 基于连通性的状态压缩DP
- TSP+dp+状态压缩的本质
- 状态压缩DP----车的摆放4
- 状态压缩dp
- pku1038状态压缩dp
- 【多校训练】ZZULIOJ 1896 985的买饮料难题
- HDU1025 nlogn的LIS
- Python 爬虫5——爬取并下载网页指定规格的图片
- Linux下静态链接库与动态链接库的区别
- 仿网易新闻分类刷新
- POJ2836 状态压缩dp不能逆向推倒的
- Java ThreadPool源码简单的解析
- ANDROID 内存分析
- Activex签名方法和工具技巧(图)
- MATLAB函数句柄、单元数组和结构
- 51NOD 1016 水仙花数 V2(打表)
- kafka同步zookeeper前移偏移量
- codeforces Inna and Dima:好题,记忆化搜索,dfs
- JavaEE(3)