一、问题一及代码
1.1问题
现有n种不同形状的宝石,每种n颗,共n*n颗。同一形状的n颗宝石分别具有n种不同的颜色c1,c2,…,cn中的一种颜色。欲将这n*n颗宝石排列成n行n列的一个方阵,使方阵中每一行和每一列的宝石都有n种不同的形状和n种不同颜色。设计一个算法,计算出对于给定的n,有多少种不同的宝石排列方案。
1.2代码
#include <iostream>
#include <vector>
using namespace std;
bool isSafe(int v, vector<vector<int>>& pos, vector<int>& row, vector<int>& col, int i, int j) {
for (int k = 0; k < pos.size(); k++) {
if (row[i] == v || col[j] == v) {
return false;
}
}
return true;
}
bool solve(vector<vector<int>>& pos, vector<int>& row, vector<int>& col, int i, int j) {
if (i == pos.size()) {
return true;
}
if (j == pos.size()) {
return solve(pos, row, col, i + 1, 0);
}
for (int v = 1; v <= pos.size(); v++) {
if (isSafe(v, pos, row, col, i, j)) {
pos[i][j] = v;
row[i] = v;
col[j] = v;
if (solve(pos, row, col, i, j + 1)) {
return true;
}
pos[i][j] = 0;
row[i] = 0;
col[j] = 0;
}
}
return false;
}
int main() {
int n;
cin >> n;
vector<vector<int>> pos(n, vector<int>(n, 0));
vector<int> row(n, 0);
vector<int> col(n, 0);
if (solve(pos, row, col, 0, 0)) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << pos[i][j] << " ";
}
cout << endl;
}
} else {
cout << "No solution" << endl;
}
return 0;
}
二、问题二及代码
2.1问题
罗密欧与朱丽叶身处一个m×n的迷宫中。每一个方格表示迷宫中的一个房间。这 m × n 个房间中有一些房间是封闭的,不允许任何人进入。在迷宫中任何位置均可沿 8 个方向进入未封闭的房间。罗密欧位于迷宫的(p,q)方格中,他必须找出一条通向朱丽叶所在的(r,s)方格的路。在抵达朱丽叶之前,他必须走遍所有未封闭的房间各一次,而且要使到达朱丽叶的转弯次数为最少。每改变一次前进方向算作转弯一次。请设计一个算法帮助罗密欧找出这样一条道路。
2.2代码
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int min_turns, total_rooms, visited_rooms;
vector<vector<int>> visited;
pair<int, int> start, end;
void dfs(vector<vector<int>>& grid, int x, int y, int dir, int turns) {
if (turns > min_turns) return; // Pruning
if (x == end.first && y == end.second) {
if (visited_rooms == total_rooms && turns < min_turns) {
min_turns = turns;
}
return;
}
for (int i = 0; i < 8; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 0 && nx < grid.size() && ny >= 0 && ny < grid[0].size() && !visited[nx][ny] && grid[nx][ny] != -1) {
visited[nx][ny] = 1;
visited_rooms++;
dfs(grid, nx, ny, i, turns + (dir != -1 && dir != i));
visited[nx][ny] = 0;
visited_rooms--;
}
}
}
int main() {
int m, n;
cin >> m >> n;
vector<vector<int>> grid(m, vector<int>(n, 0));
total_rooms = m * n;
visited = vector<vector<int>>(m, vector<int>(n, 0));
min_turns = INT_MAX;
visited_rooms = 1;
visited[start.first][start.second] = 1;
dfs(grid, start.first, start.second, -1, 0);
if (min_turns == INT_MAX) {
cout << "No solution" << endl;
} else {
cout << "Minimum turns: " << min_turns << endl;
}
return 0;
}
三、问题三及代码
3.1问题
石油传输网络通常可表示为一个非循环带权的有向图G.G中有一个称为源的顶点s,石油从顶点输送到G中其他顶点,图G中每条边的权表示该边连接的2个顶点间的距离,网络中的油压随距离的增大而减小,为保证整个输油网络的正常工作,需要维持网络的最低油压Pmin,为此需要在网络的某处或全部顶点处设置增压器,在设置增压器的顶点处油压可以升至Pmax,油压从Pmax减到Pmin可使石油传输的距离至少为d,试设计一个算法,计算网络中增压器的最优设置方案,使得用最少增压器保证石油运输的畅通。
3.2代码
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int min_boosters, total_nodes, visited_nodes;
vector<vector<int>> adj;
vector<int> visited, boosters;
void dfs(int node, int boosters_used, int distance, int Pmin, int Pmax, int d) {
if (boosters_used > min_boosters) return; // Pruning
if (distance > d) {
boosters_used++;
distance = 0;
}
if (node == total_nodes) {
if (visited_nodes == total_nodes && boosters_used < min_boosters) {
min_boosters = boosters_used;
}
return;
}
for (int i = 0; i < adj[node].size(); i++) {
int next_node = adj[node][i];
if (!visited[next_node]) {
visited[next_node] = 1;
visited_nodes++;
dfs(next_node, boosters_used, distance + adj[node][next_node], Pmin, Pmax, d);
visited[next_node] = 0;
visited_nodes--;
}
}
}
int main() {
int n, Pmin, Pmax, d;
cin >> n >> Pmin >> Pmax >> d;
total_nodes = n;
adj = vector<vector<int>>(n, vector<int>(n, 0));
visited = vector<int>(n, 0);
min_boosters = INT_MAX;
visited_nodes = 1;
visited[0] = 1;
dfs(0, 0, 0, Pmin, Pmax, d);
if (min_boosters == INT_MAX) {
cout << "No solution" << endl;
} else {
cout << "Minimum boosters: " << min_boosters << endl;
}
return 0;
}