Pagini recente » Cod sursa (job #524061) | Cod sursa (job #963295) | Istoria paginii runda/primuld/clasament | Cod sursa (job #522261) | Cod sursa (job #877448)
Cod sursa(job #877448)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>
using namespace std;
//ifstream f("gather.in");
ofstream g("gather.out");
#define nmax 752
#define Kmax 16
#define Mmax 1255
#define ll long long
#define inf (1<<29)
#define Cifmax (1<<14)
int K, n, m, Cost[Kmax+1][Kmax+1][Kmax+1] , dist[nmax], dp[(1<<Kmax)+1][Kmax+1];
set< pair<int,int> > S;
vector< pair<int, pair<int,int> > > gf[nmax];
int Det[Kmax+1];
char s[Cifmax]; int poz;
void buf(int &nr){
nr = 0;
while( s[poz] < '0' || s[poz] > '9' ){
++poz; if (poz == Cifmax){
fread(s, 1, Cifmax, stdin);
poz = 0;
}
}
while( s[poz] >= '0' && s[poz] <= '9'){
nr = nr * 10 + (s[poz] - '0');
++poz; if (poz == Cifmax){
fread(s, 1, Cifmax, stdin);
poz = 0;
}
}
}
void citeste(){
//f >> K >> n >> m;
buf(K); buf(n); buf(m);
Det[0] = 1;// detinutul Gigel
//++K;
for(int i=1; i<=K; ++i) buf(Det[i]);// f>>Det[i];
int x, y, c, d;
for(int i=1; i<=m; ++i){
//f >> x >> y >> c >> d;
buf(x); buf(y); buf(c); buf(d);
gf[x].push_back( make_pair( y, make_pair(c, d) ) );
gf[y].push_back( make_pair( x, make_pair(c, d) ) );
}
}
struct cmp{
bool operator() (const int x, const int y){
return dist[x] > dist[y];
}
};
void Dijkstra(int s, int d, int k){
for(int i=1; i<=n; ++i) dist[i] = inf;
priority_queue< int, vector<int>, cmp > Q;
dist[s] = 0; Q.push(s);
for(; Q.size(); ){
int nod = Q.top(); Q.pop();
if (nod == d) return;// am ajuns la destinatie
for(int i=0; i<gf[nod].size(); ++i){
int vc = gf[nod][i].first;
int cost = gf[nod][i].second.first;
int Maxd = gf[nod][i].second.second;// numarul maxim de detinuti
if (dist[vc] > dist[nod] + cost && Maxd >= k){
dist[vc] = dist[nod] + cost;
Q.push( vc );
}
}
}
}
void bagaDistante(){
for(int i=0; i<=K; ++i){
for(int j=i+1; j<=K; ++j){
// fac distanta minima de la al i-lea detinut la al j-lea detinut / evident si de la j la i tot atata va fi
// doar ca vreau ca pe drumul asta pe orice muchie sa ma pot duce cu K detinuti
for(int k=0; k<=K; ++k){// gigel nu e contorizat ca si detinut
Dijkstra(Det[i], Det[j], k);
Cost[i][j][k] = dist[ Det[j] ];
Cost[j][i][k] = dist[ Det[j] ];
//cout << Det[i] << " " << Det[j] << " " << k << " " << dist[j] << "\n";
}
}
}
}
void rezolva(){
// in primul rand am solutia ar fi o dinamica gen dp[conf][j] = timpul minim parcurs de detinutii din conf stiind ca ultimul
// care se alatura e al j-lea; numai ca pentru asta j-ul o sa continui un conf2 , k si imi trebuie distanta minima de la k la j
// iar acum vreau distana minima de k , j a. vand invedere ca pe orice muchie de pe drumul asta minim pot sa ma duc cu detinutii
// deci mai trebuie o dinamica dp[i][j][k] = distanta minima de la i la j stiind ca pe orice muchie de la i la j ma pot duce cu cel putin k detinuti
// fac a 2 -a dinamica
bagaDistante();
// si acum bag prima dinamica
for(int i=0; i<(1<<K); ++i) for(int j=0; j<=K; ++j) dp[i][j] = inf;
dp[0][0] = 0;// detinutul gigel de la el pornesc
int lim = (1<<K);
for(int conf = 1; conf<lim; ++conf){
int cnt = 0;
for(int j=0; j<K; ++j)
if ( conf & (1<<j) ) ++cnt;// cati detinuti am
for(int j=0; j<K; ++j){// deci sunt vreau sa ajung in j;
if ( conf & (1<<j) ){
int precConf = conf - (1<<j); // scad acest detinut
if (precConf == 0){
dp[conf][j+1] = min(dp[conf][j+1], Cost[0][j+1][cnt-1]);
continue;
}
for(int k=0; k<K; ++k){
if ( precConf & (1<<k) ){// si stiu ca vin din precConf, k
if (Cost[k+1][j+1][cnt-1] == inf || dp[precConf][k+1] == inf) continue;
dp[conf][j+1] = min(dp[conf][j+1], dp[precConf][ k+1 ] + (Cost[ k+1 ][ j+1 ][cnt-1] * (cnt) ) );
}
}
}
}
}
int Min = inf;
for(int i=1; i<=K; ++i) Min = min( dp[lim-1][i], Min );
cout << Min << "\n";
g << Min << "\n";
}
int main(){
freopen("gather.in", "r", stdin);
citeste();
rezolva();
//9 f.close();
g.close();
return 0;
}