您的位置:首页 > 其它

UVa 11008 Antimatter Ray Clearcutting / 状态压缩DP

2014-03-13 12:51 417 查看
一看题目就知道是状态压缩 DP

然后n棵树至少要砍掉m棵

每次可以去掉一整行的树 斜着也可以 求最少的次数

开始不知道怎么存一整行 百度了 然后是用一个二维数组a[i][j] 里面一个二进制 表示可以朝i j这个发现去掉的树

然后i == j的时候我是 a[i][j] = 1<i 表示一棵树的情况 因为不知道方向

网上大多数是记忆化搜索 递推也行

还需好好消化

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 18;
int a[maxn][maxn];
int dp[1<<maxn];
int x[maxn];
int y[maxn];
int bitcount(int x)
{
	int ret = 0;
	while(x)
	{
		if(x&1)
			ret++;
		x >>= 1;
	}
	return ret;
}
	
int main()
{
	int cas = 1;
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int n, m;
		scanf("%d %d", &n, &m);
		for(int i = 0; i < n; i++)
			scanf("%d %d", &x[i], &y[i]);
		for(int i = 0; i < n; i++)
			for(int j = 0; j < n; j++)
			{
				a[i][j] = 0;
				if(i == j)
				{
					a[i][j] = 1<<i;
					continue;
				}
				for(int k = 0; k < n; k++)
				{
					//(x[i]-x[k])/(y[i]-y[k]) == (x[j]-x[k])/(y[j]-y[k])
					if((x[i]-x[k])*(y[j]-y[k]) == (x[j]-x[k])*(y[i]-y[k]))
						a[i][j] |= (1<<k);
				}
			}
		int ans = 999999999;
		/*for(int i = 0; i < n; i++)
		{
			for(int j = 0; j < n; j++)
			{
				printf("%d ", a[i][j]);
			}
			puts("");
		}*/
		dp[0] = 0;
		for(int s = 1; s < (1<<n); s++)
		{
			int cnt = bitcount(s);
			int i, j;
			dp[s] = 999999999;
			for(i = 0; i < n; i++)
				if(s & (1<<i))
					break;
			for(j = i; j < n; j++)
			{
				if(s & (1<<j))
				{
					dp[s] = min(dp[s], dp[s&(~a[i][j])]+1);
					if(cnt >= m)
						ans = min(ans, dp[s]);
				}
			}
			
		}
		printf("Case #%d:\n", cas++);
		printf("%d\n", ans);
		if(T)
			puts("");
	}
	return 0;
}
/*
2
4
4
0 0
0 1
1 0
1 1
9
7
0 0
1 1
0 2
2 0
2 2
3 0
3 1
3 2
3 4
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: