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;
}