您的位置:首页 > 其它

uva 11008(dp + 状态压缩)

2014-12-31 17:39 218 查看
题意:有n个点,然后需要删除m个点,在一条线上的点可以被删除,问最少几条线可以删除到m个点。

题解:状态压缩,s[i][j]存了i,j所在直线穿过的所有点,并把的他们的标志位设为1,然后递归,状态数sta的所有位设为1,删除掉的设为0,结束标志是剩余1的位数小于n-m,状态数sta和s[i][j]与非运算后可以删除和i,j在一条线上的所有点,f[sta]表示在sta状态下最少条线能删m个点。

状态转移方程:

f[sta] = min(f[sta], dp(sta & (~s[i][j])) + 1);


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 20;
const int M = 1 << 20;
const int INF = 0x3f3f3f3f;
int n, m, s

, f[M];

struct Point {
int x, y;
}p
;

int dp(int sta) {
if (f[sta] != -1)
return f[sta];
int k = 0;
for (int i = 0; i < n; i++)
if (sta & (1 << i))
k++;
if (n - m >= k )
return f[sta] = 0;
if (k == 1)
return f[sta] = 1;
f[sta] = INF;
for (int i = 0; i < n; i++) {
if (sta & (1 << i) ) {
for (int j = i + 1; j < n; j++)
if (sta & (1 << j) )
f[sta] = min(f[sta], dp(sta & (~s[i][j])) + 1);
}
}
return f[sta];
}

bool judge(int i, int j, int k) {
if ((p[i].y - p[j].y) * (p[i].x - p[k].x) == (p[i].x - p[j].x) * (p[i].y - p[k].y))
return true;
return false;
}

int main() {
int t, cas = 1;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
memset(f, -1, sizeof(f));
memset(s, 0, sizeof(s));
for (int i = 0; i < n; i++)
scanf("%d%d", &p[i].x, &p[i].y);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if (i == j)
continue;
for (int k = n - 1; k >= 0; k--) {
s[i][j] <<= 1;
if (judge(i, j, k))
s[i][j]++;
}
}
printf("Case #%d:\n%d\n", cas++, dp((1 << n) - 1));
if (t)
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uva dp