第五章作业

一、问题一及代码

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

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值