dfs+bfs65分求调
查看原帖
dfs+bfs65分求调
970949
CleverSea楼主2024/8/27 11:21
#include <bits/stdc++.h>
#define int long long
using namespace std;

int n, m, k;
int s[2510], bvis[2510][2510]; // s数组记录景点分数,vis作为广搜的数组,rec作为记忆化搜索数组
bool r[2510][2510], flag[2510]; // r[i][j] == 1表示i与j之间有道路直连,flag[i] == 1表示景点去过了
queue<int> q; // 广搜队列

void bfs(int start)
{
    q.push(start);
    while (!q.empty())
    {
        int now = q.front();
        q.pop();
        if (bvis[start][now] >= k) continue; // 如果换乘次数已经达到k次,就不再继续
        for (int i = 1; i <= n; i++) // 枚举家和每个景点
        {
            if (r[now][i] == 0 || bvis[start][i] != -1) continue; // 如果没有路相连(r[now][i] == 0)或已经找过了(vis[i] != -1)则跳过
            bvis[start][i] = bvis[start][now] + 1;
            q.push(i);
        }
    }
}

int dfs(int p, int x) // p为当前是第几个景点,x为当前的景点编号
{
    bfs(x); // 广搜求出换乘次数
    bvis[x][x] = -1;
    int sum = 0;
    if (p > 4) return 0;
    if (p == 4) // 如果p=4则要考虑这个景点能否回到家
    {
        if (bvis[x][1] == -1)
        {
            return -1e9;
        }
    }
    for (int i = 2; i <= n; i++) // 枚举每个景点,取最大分数
    {
        if (bvis[x][i] == -1 || flag[i] == 1) continue; // 如果无法到达(vis[i] == -1)或这个景点去过了(flag[i] == 1)则跳过
        flag[i] = 1; // 标记这个景点去过了
        sum = max(sum, dfs(p + 1, i) + s[x]);
        flag[i] = 0; // 回溯
    }
    return sum; // 存储并返回
}

signed main()
{
    ios::sync_with_stdio(false); // 读写加速
    cin >> n >> m >> k;
    for (int i = 2; i <= n; i++) cin >> s[i]; // 读入景点分数
    while(m--) // 读入道路直连
    {
        int a, b;
        cin >> a >> b;
        r[a][b] = r[b][a] = 1; // 使用r数组存储两点是否有道路直连,1为有,0为无
    }
    memset(bvis, -1, sizeof(bvis));
    cout << dfs(0, 1) << endl; // dfs找出最大分数
    return 0;
}

2024/8/27 11:21
加载中...