poj1129 poj1106


poj1129

算法思想:DFS, 回溯法, 子集树,四色定理

初始认为只需一种颜色(色数为1),当颜色数不能满足涂色要求时,就再添加一种颜色(色数加1)

bool OK(int id, int c) 用于判断颜色c是否可以给点id着色


//poj1129 图的染色问题,DFS,子集树 
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int maxn = 128;
bool pic[maxn][maxn], finished;
int n, color[maxn], ans;
bool OK(int id, int c) {
	for (int i = 'A'; i < n; ++i) {
		if(pic[id][i] && c == color[i]) //两点相邻,且颜色相同,kill 
			return false; 
	}
	return true;
}
void DFS(int id, int total) {
	if (finished) {
		return;
	}
	if (id >= n || ans >= 4) { //四色定理用于减枝 
		finished = true;
		return;
	}
	for (int i = 1; i <= total; ++i) { //为第id个点,选择第i种颜色 
		if (OK(id, i)) {
			color[id] = i;
			DFS(id + 1, total);
			color[id] = 0; //这里没有用那个图论中着色的算法(忘了名字),用的回溯法
		}
	}
	if (!finished) { //total种颜色无法完成染色任务,在加一种颜色 
		ans++;
		DFS(id, total + 1);
	}
}
int main()
{
	while((cin >> n) && n) {
		memset(pic, 0, sizeof(bool) * maxn * maxn);
		for (int i = 0; i < n; ++i) {
			string str;
			cin >> str;
			for (int i = 2; i < str.length(); ++i) {
				pic[str[0]][str[i]] = pic[str[i]][str[0]] = true;
			}
		} //无向图已构建好,下面对图进行着色(四色定理用于减枝)
		ans = 1;
		n += 'A';
		finished = false;
		DFS('A', 1);
		cout << ans;
		if (ans == 1) {
			cout << " channel needed." << endl;
		}
		else {
			cout << " channels needed." << endl;
		}
	}	 
	
	return 0;
}


poj1160

动态规划

#include <cstdio> 
#include <algorithm>
#define INF 0x3f3f3f3f
#define N 35
const int maxn = 307;
int dp[maxn][N], dis[maxn][maxn];  
int x[maxn];
int main()
{
	int v, p;
	while(~scanf("%d%d", &v, &p)) {
		for (int i = 1; i <= v; ++i) {
			scanf("%d", x + i);
		}
		for (int i = 1; i <= v; ++i) {
			dis[i][i] = 0;//dis[i][j]表示在第i个村庄和第j个村庄建建立一个邮局的最短距离 
			for (int j = i + 1; j <= v; ++j)
				dis[i][j] = dis[i][j - 1] + x[j] - x[(i + j) >> 1];
			dp[i][i] = 0; // i个村长i个邮局 
			dp[i][1] = dis[1][i]; //前i个村庄建立一个邮局 
		} 
		for (int j = 2; j <= p; ++j) { //dp[i][j]表示前i个村庄建立j个邮局的所求最短距离
			for (int i = j + 1; i <= v; ++i) { //前i个村庄 
				dp[i][j] = INF;
				for (int k = j - 1; k < i; ++k) { //j - 1 < k < i
					dp[i][j] = std::min(dp[i][j], dp[k][j - 1] + dis[k + 1][i]); 
				}
			}
		}
		printf("%d\n", dp[v][p]);
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值