제출 #1160537

#제출 시각아이디문제언어결과실행 시간메모리
1160537jus_teng여행하는 상인 (APIO17_merchant)C++20
0 / 100
1096 ms3284 KiB
#include <bits/stdc++.h>
using namespace std;

/*SPFA algorithm adapted from https://cp-algorithms.com/graph/bellman_ford.html
Binary Search algorithm adapted from https://cp-algorithms.com/num_methods/binary_search.html
Modifications:
- Transformed state space where each node is (market, item state)
- Total number of states is n * (k + 1)
- k + 1 is item purchases
- vector<ld> dist(v, 0) set to 0
- Start SPFA from only the first market (reduces unnecessary computations)
- Use deque<int> instead of queue<int> for better performance (SLF optimization)
- Limit visitCount threshold to 2 * v for better cycle detection
- if (dist[u] + weight > dist[nextState] + eps) to maximize profit
- Binary search over lambda*/

typedef long long ll;
typedef double ld;

const ll maxN = 100;
const ll maxK = 1000;
const ld inf = 1e18;
const ld eps = 1e-12;

ll n, m, k;
vector<vector<pair<ll, ll>>> adj;
vector<vector<ll>> b, s;

bool SPFA(ld lambda) {
    ll v = n * (k + 1);
    vector<ld> dist(v, -inf);  // Use -inf instead of 0 for maximization
    vector<int> visitCount(v, 0);
    vector<bool> inQueue(v, false);
    deque<int> q;

    // Start only from the first market (more efficient)
    q.push_back(0);
    dist[0] = 0;
    inQueue[0] = true;
    visitCount[0] = 1;

    while (!q.empty()) {
        int u = q.front();
        q.pop_front();
        inQueue[u] = false;

        ll currentMarket = u / (k + 1);
        ll itemState = u % (k + 1);

        if (itemState == 0) {
            for (ll j = 0; j < k; j++) {
                if (b[currentMarket][j] != -1) {
                    ll nextState = currentMarket * (k + 1) + (j + 1);
                    ld weight = -b[currentMarket][j] + eps;

                    if (dist[u] + weight > dist[nextState] + eps) {
                        dist[nextState] = dist[u] + weight;
                        if (!inQueue[nextState]) {
                            if (!q.empty() && dist[nextState] > dist[q.front()])
                                q.push_front(nextState);
                            else
                                q.push_back(nextState);
                            inQueue[nextState] = true;
                            visitCount[nextState]++;
                            if (visitCount[nextState] > 2 * v) return true;
                        }
                    }
                }
            }
        } else {
            ll j = itemState - 1;
            if (s[currentMarket][j] != -1) {
                ll nextState = currentMarket * (k + 1);
                ld weight = s[currentMarket][j] + eps;

                if (dist[u] + weight > dist[nextState] + eps) {
                    dist[nextState] = dist[u] + weight;
                    if (!inQueue[nextState]) {
                        if (!q.empty() && dist[nextState] > dist[q.front()])
                            q.push_front(nextState);
                        else
                            q.push_back(nextState);
                        inQueue[nextState] = true;
                        visitCount[nextState]++;
                        if (visitCount[nextState] > 2 * v) return true;
                    }
                }
            }
        }

        for (auto p : adj[currentMarket]) {
            ll nextMarket = p.first;
            ll travelTime = p.second;
            ll nextState = nextMarket * (k + 1) + itemState;
            ld weight = -lambda * travelTime + eps;

            if (dist[u] + weight > dist[nextState] + eps) {
                dist[nextState] = dist[u] + weight;
                if (!inQueue[nextState]) {
                    if (!q.empty() && dist[nextState] > dist[q.front()])
                        q.push_front(nextState);
                    else
                        q.push_back(nextState);
                    inQueue[nextState] = true;
                    visitCount[nextState]++;
                    if (visitCount[nextState] > 2 * v) return true;
                }
            }
        }
    }
    return false;
}

ll binSearch() {
    ld low = 0.0;
    ld high = 1e12;
    
    for (int iter = 0; iter < 100; iter++) {
        ld mid = (low + high) / 2.0;
        if (SPFA(mid)) {
            low = mid;
        } else {
            high = mid;
        }
    }
    
    return (ll)floor(low);
}

int main() {
    scanf("%lld %lld %lld", &n, &m, &k);
    b.assign(n, vector<ll>(k));
    s.assign(n, vector<ll>(k));
    adj.resize(n);

    for (ll i = 0; i < n; i++) {
        for (ll j = 0; j < k; j++) {
            scanf("%lld %lld", &b[i][j], &s[i][j]);
        }
    }

    for (ll i = 0; i < m; i++) {
        ll from, to, time;
        scanf("%lld %lld %lld", &from, &to, &time);
        adj[from - 1].emplace_back(to - 1, time);
    }

    printf("%lld\n", binSearch());
    return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

merchant.cpp: In function 'int main()':
merchant.cpp:131:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  131 |     scanf("%lld %lld %lld", &n, &m, &k);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
merchant.cpp:138:18: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  138 |             scanf("%lld %lld", &b[i][j], &s[i][j]);
      |             ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
merchant.cpp:144:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  144 |         scanf("%lld %lld %lld", &from, &to, &time);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...