Cod sursa(job #2649965)

Utilizator victorzarzuZarzu Victor victorzarzu Data 16 septembrie 2020 22:14:18
Problema Gather Scor 20
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.81 kb
#include <bits/stdc++.h>
#define point pair<int, int> 
#define dist first
#define nod second
#define oo 1e10
 
using namespace std;
ifstream fin("gather.in");
ofstream fout("gather.out");
 
int n, k, m;
vector<tuple<int, int, int>> g[755];
vector<point> detinuti;
unsigned long long distanta[755][755], dp[(1 << 16) + 5][20], graf[20][20][20];
queue<int> q;
bitset<755> viz;
 
void Read()
{
  int w, x, y, z, nr = 0;
  fin>>k>>n>>m;
  detinuti.push_back({1, ++nr});
  for(int i = 1;i <= k;++i)
    fin>>w, detinuti.push_back({w, ++nr});
  for(int i = 1;i <= m;++i)
  {
    fin>>w>>x>>y>>z;
    g[w].push_back({x, y, z}); g[x].push_back({w, y, z});
  }
}
 
void bellman(int start)
{
  viz.reset();
  for(int i = 0;i <= 750;++i)
    for(int j = 0;j <= 750;++j)
      distanta[i][j] = oo;
  for(int i = 0;i <= k;++i)
    distanta[start][i] = 0;
  q.push(start);
  viz.set(start);
  int nod, vecin, cost, cap;
  bool mod = false;
 
  while(!q.empty())
  {
    nod = q.front();
    q.pop();
 
    for(auto it : g[nod])
    {
      vecin = get<0>(it), cost = get<1>(it), cap = get<2>(it);
      mod = false;
 
      for(int i = 0;i <= cap;++i)
        for(int j = i;j <= cap;++j)
          if(distanta[vecin][i] > distanta[nod][j] + cost)
          {
            mod = true;
            distanta[vecin][i] = distanta[nod][j] + cost;
          }
      if(!viz.test(vecin) && mod)
        q.push(vecin);
      viz.set(vecin);
    }
 
    viz.reset(vecin);
  }
}
 
void solve()
{
  for(int i = 1;i <+ (1 << (k + 1));++i)
    for(int j = 1;j <= k + 1;++j)
      dp[i][j] = oo;
  dp[1][1] = 0;
  int nr = 0;
  for(int i = 1;i <= (1 << (k + 1));++i)
    if(i & 1)
    {
      nr = 0;
      for(int h = 1;h <= k;++h)
        if(i & (1 << h)) ++nr;
      for(int j = 1;j <= k + 1;++j)
        for(int h = 1;h <= k + 1;++h)
          if(j != h)
          {
            if(!(i & (1 << (j - 1))) && graf[j][h][nr] != oo)
              dp[i + (1 << (j - 1))][j] = min(dp[i + (1 << (j - 1))][j], dp[i][h] + (nr + 1) * graf[j][h][nr]);
            if((i & (1 << (j - 1))) && graf[j][h][nr] != oo)
              dp[i][j] = min(dp[i][j], dp[i][h] + (nr + 1) * graf[j][h][nr]);
          }
    }
  unsigned long long rez = oo;
  for(int i = 1;i <= k + 1;++i)
    rez = min(rez, dp[(1 << (k + 1)) - 1][i]);
  fout<<rez;
}
 
void make_graph()
{
  int nr = 0;
  for(auto it : detinuti)
    {
      ++nr;
      bellman(it.first);
      for(auto it1 : detinuti)
        for(int i = 0;i <= k;++i)
          if(it.first != it1.first && distanta[it1.first][i] < oo)
            graf[it.second][it1.second][i] = distanta[it1.first][i];
    }
  /*for(int i = 1;i <= k + 1;++i, cout<<'\n')
    for(int j = 1;j <= k + 1;++j)
      for(int h = 0;h <= k;++h)
        if(i != j)
           cout<<i<<" "<<j<<" "<<graf[i][j][h]<<" "<<h<<'\n';*/
}
 
int main()
{
  Read();
  make_graph();
  solve();
  return 0;
}