程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> uva11008 - Antimatter Ray Clearcutting(二進制+記憶化搜索)

uva11008 - Antimatter Ray Clearcutting(二進制+記憶化搜索)

編輯:C++入門知識

uva11008 - Antimatter Ray Clearcutting(二進制+記憶化搜索)


 

 

題目大意:給出n棵樹的坐標,每次砍樹能夠將在同一直線上的樹一起砍掉,然後給出要求你至少砍掉的樹的數量,問你要達到這個要求需要砍多少次。

 

解題思路:因為這題的樹的數量比較小(16), 並且只有砍和不砍兩種選擇,可以用二進制數將狀態表示出來。大致思路是:每次都將當前狀態下的還沒砍的樹中選擇兩棵,在將和這兩個樹在同一直線上的樹一起砍掉,得到新的狀態。如果已經》=K棵了,就可以返回0了。一般來說,每次選擇兩棵樹一起砍掉比較優,除非只剩下一棵樹了。所以應該要先預處理出每兩棵樹和它們在同一直線上的樹,並且這個狀態可以也用二進制表示。

 

代碼:

 

#include 
#include 

const int maxn = 1<<17;
const int M = 20;

int dp[maxn];
int n, k;
int tree[M][2];
int line[M][M];

bool judge (int i, int j, int k) {

	int a = (tree[j][1] - tree[i][1]) * (tree[k][0] - tree[j][0]);
	int b = (tree[k][1] - tree[j][1]) * (tree[j][0] - tree[i][0]);
	return a == b ? true : false;
}

int Min (const int a, const int b) { return a < b ? a: b; }

void init () {

	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			line[i][j] = 0;
			for (int l = 0; l < n; l++) {
				
				if (judge (i, j, l)) {
					line[i][j] |= (1<= k)
		return ans = 0; 

	int flag = 0;
	for (int i = 0; i < n; i++) {
		if (((1 << i) & s) == 0) {
			for (int j = i + 1; j < n; j++) {
				if (((1 << j) & s) == 0) {
					flag = 1;
					ans = Min (ans, DP(s | line[i][j]) + 1);
					//printf (%d %d %d
, s, s | line[i][j], ans);
				}
			}
			if (!flag) { 
				ans = Min (ans, DP(s | (1<

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved