Cod sursa(job #2983240)

Utilizator BlueLuca888Girbovan Robert Luca BlueLuca888 Data 21 februarie 2023 21:26:48
Problema Wanted Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.78 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin  ("wanted.in");
ofstream fout ("wanted.out");

const int MAX_N = 200;
int n;
struct oras{
    int x, y;
    inline bool operator < (const oras &rhs) const{
        return x < rhs.x;
    }
} o[MAX_N + 5];

static inline long long come_from_left(int st, int dr), come_from_right(int st, int dr);

long long mem_cfr[MAX_N + 5][MAX_N + 5];
static inline long long come_from_right(int st, int dr){
    if(mem_cfr[st][dr] == -1){
        if(st == dr){
            mem_cfr[st][dr] = o[st].y;
        }else{
            long long best;
            for(int md=st; md<=dr; md++){
                ///merg de la o[dr] la o[md]
                long long answer = abs(o[dr].x - o[md].x);

                ///vizitez oras-ul o[md]
                answer += 2 * o[md].y;

                ///in functie de raspuns ma duc in stanga respectiv dreapta
                if(st < md && md < dr){
                    answer += max(abs(o[md].x - o[md-1].x) + come_from_right(st, md-1), abs(o[md].x - o[md+1].x) + come_from_left(md+1, dr));
                }else if(st < md){
                    answer += abs(o[md].x - o[md-1].x) + come_from_right(st, md-1);
                }else if(md < dr){
                    answer += abs(o[md].x - o[md+1].x) + come_from_left(md+1, dr);
                }

                ///cel mai bun traseu
                if(md == st)
                    best = answer;
                else
                    best = min(best, answer);
            }
            mem_cfr[st][dr] = best;
        }
    }
    return mem_cfr[st][dr];
}

long long mem_cfl[MAX_N + 5][MAX_N + 5];
static inline long long come_from_left(int st, int dr){
    if(mem_cfl[st][dr] == -1){
        if(st == dr){
            mem_cfl[st][dr] = o[st].y;
        }else{
            long long best;
            for(int md=st; md<=dr; md++){
                ///merg de la o[st] la o[md]
                long long answer = abs(o[st].x - o[md].x);

                ///vizitez oras-ul o[md]
                answer += 2 * o[md].y;

                ///in functie de raspuns ma duc in stanga respectiv dreapta
                if(st < md && md < dr){
                    answer += max(abs(o[md].x - o[md-1].x) + come_from_right(st, md-1), abs(o[md].x - o[md+1].x) + come_from_left(md+1, dr));
                }else if(st < md){
                    answer += abs(o[md].x - o[md-1].x) + come_from_right(st, md-1);
                }else if(md < dr){
                    answer += abs(o[md].x - o[md+1].x) + come_from_left(md+1, dr);
                }

                ///cel mai bun traseu
                if(md == st)
                    best = answer;
                else
                    best = min(best, answer);
            }
            mem_cfl[st][dr] = best;
        }
    }
    return mem_cfl[st][dr];
}

int main (){
    ios_base::sync_with_stdio(false);
    fin.tie(nullptr), fout.tie(nullptr);

    fin>>n;
    for(int i=1; i<=n; i++)
        fin>>o[i].x>>o[i].y;
    sort(o+1, o+n+1);

    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            mem_cfl[i][j] = mem_cfr[i][j] = -1;

    long long sol;
    for(int i=1; i<=n; i++){
        long long answer = abs(0 - o[i].x) + o[i].y;
        if(1 < i && i < n){
            answer += o[i].y + max(abs(o[i].x - o[i-1].x) + come_from_right(1, i-1), abs(o[i].x - o[i+1].x) + come_from_left(i+1, n));
        }else if(1 < i){
            answer += o[i].y + abs(o[i].x - o[i-1].x) + come_from_right(1, i-1);
        }else if(i < n){
            answer += o[i].y + abs(o[i].x - o[i+1].x) + come_from_left(i+1, n);
        }

        if(i == 1)
            sol = answer;
        else
            sol = min(sol, answer);
    }
    fout<<sol;
    return 0;
}