9 Ekim 2014 Perşembe

Balanced Cow Breeds

   Size parantezlerden oluşan N uzunluğunda bir dizi veriliyor. Bu parantezleri H ve G grubu olarak ikiye ayıracaksınız, öyle ki her iki grubun parantezleri kendi içinde düzenli parantez olacak. Sizden bunun kaç farklı şekilde yapılabileceğini bulmanız isteniyor. Çıktıya 2012'ye göre modunu yazdırıyorsunuz.    Düzenli parantez dizileri açma ve kapama parantezleri sayısının birbirine eşit olduğu ve soldan sağa giderken kapamaların sayısının açmaları hiçbir zaman geçmediği parantez dizileridir. Örneğin: "()","(())", "(())()"

Kısıtlamalar

1 <= N <= 1000

Girdi Formatı

Tek satırda parantezlerden oluşan N uzunluğunda dizi

Örnek Girdi

(())

Çıktı Formatı

Tek satırda istenenin kaç farklı şekilde yapılabileceğinin 2012'ye göre modu.

Örnek Çıktı

6

Çıktı Açıklaması

6 gruplama:

(())
HHHH

(())
GGGG

(())
HGGH

(())
GHHG

(())
HGHG

(())
GHGH


ÇÖZÜM

Soru iki boyutlu dinamik kullanılarak çözülebilir. dp[i][j] sunu belirtiyor: i indisine kadar olan parantezleri bir sekilde gruplamisim ve H grubuna aldigim acmalarin sayisi kapamalarinkinden j fazla iken i ile n arasini kac farkli sekilde uygun sekilde gruplandirabilirim. Herhangi bir durumda iki secim yapabilirim: i. parantez ya H olacak ya da G. Dinamik yapmadan once dizinin her bir indisi icin oraya kadarki "acmalar - kapamalar"i hesaplamak dinamigi yaparken ise yarayacaktir.

6 Ekim 2014 Pazartesi

Revamping Trails

Ipucu: soru shortest path sorusu ve dijkstra nin algoritmasiyla cozulebilir. Soruda k sinirinin kucuk olmasindan faydalanacagiz. K*n tane toplam durum var.

Cozum metnini soru ile birlikte en kisa surede koyacagim. Umarim ipucu faydali olur

4 Ekim 2014 Cumartesi

Digraphs

Sizden kare şeklinde bir tablo doldurmanız isteniliyor. Bu tablo küçük harflerden oluşacak ve max 20x20'lik bir kare olabilecek. Bu tabloyu doldururken tabi ki bazı kurallara uymanız gerek.

Size n tane 2 küçük harften oluşan stringler verilecek. Örneğin stringlerden biri "xy" olsun. Sizin dolduracağınız tabloda y, x'in bir sağında veya x'in bir altında olamaz.

Amacınız olabildiğince büyük bir kare tablo oluşturmak. Ayrıca bu kare çok büyük olabileceği için sizden max 20x20'lik bir kare istenmektedir.

Input Format
İlk satırda T:Test Case sayısı
Case'in ilk satırı n: Yasaklı string sayısı
Sonraki n satırda yasaklı stringler

Output Format
Kurallara uyan ve size'i max 20x20 olan bir kare tablo

Constraints
0 <= n <= 676

Input
2
628
aa
az
ba
bb
bc
...
by
ca
cb
cc
...
cy
...
...
ya
yb
yc
...
yy
za
zb
zc
...
zy
zz
2
aa
bb

Output
aw
wz
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
abababababababababab
babababababababababa
_______________________________

Linkler

Soru: http://codeforces.com/gym/100299 (K sorusu)
pdf: http://codeforces.com/gym/100299/attachments/download/2035/20132014-acm-icpc-central-european-regional-contest-cerc-13-en.pdf
Solutions: http://cerc.tcs.uj.edu.pl/2013/data/cerc2013solutions.pdf
_______________________________

Çözüm

Alfabenin 26 harfini birer node kabul edelim. Başlangıçta tüm nodelar arasında yol olan tam graph oluşturalım. Yasaklı stringler verildikçe yolları silelim. Oluşan graph'ımızda 2 farklı ihtimal vardır. Ya cycle buluncak ya da bulunmayacak. Bu 2 ihtimale göre farklı tablo oluşturma stratejileri izleyeceğiz.

Cycle varsa

Herhangi bir cycle'i kullanarak kolaylıkla 20x20'lik kare şeklinde bir tablo oluşturabiliriz. Sırasıyla "abc" diye bir cycle olduğunu düşünelim. İlk satırı "abcabc..." şeklinde oluştururuz ve her sonraki satırda ilk karakterimizi bir kaydırırız. 2.satırda "bcabca...", 3.satıtda "cabcab...", 4.satırda tekrar "abcabc..." olur. Peki cycle'i nasıl bulabiliriz?
Yanlış yaklaşım: Akla ilk gelen SCC yapmak oluyor ki kodlaması yapacağımız işe göre uzun. SCC kodlamanın diğer bir problemi elimize gelen SCC'nin sıralı bir şekilde olmaması. Örneğin cycle sırasıyla "abc" olsun. Bizim elimize "acb" şeklinde geçebilir. Bunun için ekstradan SCC'yi gezme sırasına göre sıralamamız gerekecek ki işimiz uzayacak ve kod bazen patlayacak.( Ben ve Kamil beceremedik :( )
Cycle bulma: Dfs'i kodlarken mark array'ini 0-1 şeklinde tutarız. Burada array'i 0-1-2 şeklinde tutacağız ve ek olarak Stack kullanacağız. Bir node'a ilk kez geldiysek node'un mark'ini 2 yapacağız ve stack'e atacağız. Fonksiyondan çıkarken mark'i 1 yapacağız ve stack'ten çekeceğiz. Eğer ki bu node'a önceden gelindiyse ve mark'i 2 ise bu node hala stack'tedir ve cycle vardır. Stack'ten bu node gelene kadar node'ları çekeriz ve her gelen node'ları cycle listemizin başına atarız. Bundan sonra geriye kalan tek şey tabloyu oluşturmak.

Cycle yoksa

DP kullanarak en uzun yolu buluruz. Amacımız KxK'lık kare oluşturmak ve bunu oluştururken 2*k-1 uzunluğunda bir yol bulmak. Eğer en uzun yolumuz 2*k uzunluğunda ise ilk veya son karakterini sileriz. Stratejimiz şöyle olacak... Tablonun ilk satırını en uzun yolumuzun ilk k karakteri ile dizelim. Ardından gelen her satırda ilk karakteri bir kaydıralım. Örneğin yolumuz "abcdef" ise uzunluk çift olduğu için son karakteri sileriz. "abcde" stringi kalır. İlk satır "abc", sonraki satır"bcd", ondan sonraki satır "cde" olur.
_______________________________

Kod

#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <stack>
#define  pb       push_back
using namespace std;

int T,n;
int dp[26];
int best[26];
int mark[26];
int ar[26][26];
vector<int>v;
stack<int>sta;

void Cycle()
{
  int sz=v.size();
  for(int i=0 ; i<20 ; i++)
  {
    int bas=i%sz;
    for(int j=bas ; j<bas+20 ; j++)
      printf("%c",v[j%sz]+'a');
    printf("\n");
  }
}

int f(int node)
{
  if(v.size())      return dp[node];
  if(mark[node]==1) return dp[node];
  if(mark[node]==2)
  {
    while(sta.top()!=node)
    {
 v.pb(sta.top());
 sta.pop();
}
v.pb(node);
reverse(v.begin(),v.end());
Cycle();
return dp[node];
  }
  dp[node]=1;
  mark[node]=2;
  sta.push(node);
  for(int i=0 ; i<26 ; i++)
    if(!ar[node][i])
    {
 int x=f(i)+1;
 if(v.size())   break;
 if(x>dp[node]) dp[node]=x,best[node]=i;
}
  if(!sta.empty()) sta.pop();
  mark[node]=1;
  return dp[node];
}

void Reset()
{
  v.clear();
  memset(ar,0,sizeof(ar));
  memset(mark,0,sizeof(mark));
  while(!sta.empty()) sta.pop();
}

int main()
{
  scanf("%d",&T);
  while(T--)
  {
Reset();
    scanf("%d",&n);
    for(int i=0 ; i<n ; i++)
    {
 char s[5];
 scanf("%s",s);
 ar[s[0]-'a'][s[1]-'a']=1;
}
int b1=0,b2=0;
for(int i=0 ; i<26 ; i++)
 if(!mark[i])
 {
   int x=f(i);
   if(x>b1) b1=x,b2=i;
 }
if(v.size()) continue;
if(b1%2==0)  b1--;
v.pb(b2);
for(int i=1,x=b2 ; i<b1 ; i++)
{
 x=best[x];
 v.pb(x);
}
for(int i=0 ; i<(b1+1)/2 ; i++,printf("\n"))
 for(int j=0 ; j<(b1+1)/2 ; j++)
   printf("%c",'a'+v[i+j]);
  }
  return 0;
}

Cow Jogging

Soru Metni:
Sarikiz fazla kilolarindan kurtulmak icin, tepedeki ahirindan, gole kadar
yuruyus yapmak istiyor. Yuruyus sirasinda hep asagiya inecek ve geri
donerken de sallana sallana gelecek. Sarikiz sikilmamak icin hep ayni
yoldan gitmek istemiyor ayrica cok fazla yurumek istemedigi icin de
uzun yollari kullanmak istemiyor.

Ciftlikte toplam M (1 <= M <= 10,000) adet patika var. Bu patikalar otlaklari
birbirine bagliyor. Sirayla 1..N (1 <= N <= 1000) olarak numaralandirilmislar.
Bu numuralandirma yapilirken eger X>Y ise, otlak X'ten otlay Y'ye giden patika
yokul asagi. Otlak N en tepede ve Sarikiz'in yuruyuse baslayacagi ahir burada,
gol otlak 1'de bulunuyor. Otlak 1 en asagida.

Sarikiz'a otlak N'den otlak 1'e giden en kisa K (1 <= K <= 100) yolun uzunlugunu
hesaplamasi konusunda yardimci olunuz. Eger iki yol farkli patika dizilerinden
olusuyorsa farkli kabul ediliyorlar. Size X_i'den Y_i'ye giden patikalarin listesi
uzunluklari ile birlikte verilecek: (X_i, Y_i, D_i) (1 <= Y_i < X_i; Y_i < X_i <= N),
D_i (1 <= D_i <= 1,000,000).

SORUNUN ISMI: cowjog

GIRDI BICIMI:

* Satir 1: Boslukla ayrilmis uc tamsayi: N, M, ve K

* Satirlar 2..M+1: Satir i+1 yokus asagi bir yolu uc tamsayi ile tarif ediyor:
                               X_i, Y_i, ve D_i

ORNEK GIRDI (dosya cowjog.in):

5 8 7
5 4 1
5 3 1
5 2 1
5 1 1
4 3 4
3 1 1
3 2 1
2 1 1

GIRDI BICIMI:

* Satirlar 1..K: Satir i, i'inci en kisa yolun uzunlugunu iceriyor. Eger boyle bir yol
               mevcut degilse -1. Eger birden fazla en kisa yolun uzunlugu ayni ise, bu uzunlugun
               her yol icin ayri yazilmasi gerekiyor.

ORNEK CIKTI (dosya cowjog.out):

1
2
2
3
6
7
-1

CIKTININ ACIKLAMASI:

Yollar (5-1), (5-3-1), (5-2-1), (5-3-2-1), (5-4-3-1), (5-4-3-2-1).

Link: http://cerberus.delosent.com:790/MAR08

Çözüm:
Bize cycle olmayan bir graph verilmiş ve bu graph taki node lar zaten sıralı olduğu için dynamic programming güzel bir yaklaşım olur.
Varsayın ki i>=1 olmak üzere bütün i’ler için o node a ulaşan en kısa K yolu biliyoruz. Bu durumda (i-1). node a ulaşan en kısa K yolu bulmak için bu node una giren kenarları göz önünde bulundurmamız gerekiyor. Bu node a giren kenarların sayısı d olsun. Zaten d kenarın diğer ucundaki node lar için en kısa K yolu hesapladığımız için d*K yol içinden en kısa K tanesi (i-1). node a ulaşan en kısa  K yol olmuş olacaktır. Yöntemimiz her node için d*K zamana ihtiyaç duymaktadır ve graph ın genelinde bu rakam O(M*K) ya eşit olacaktır. M=10,000 ve K=100 olduğu için toplam işlem sayısı 1,000,000 dur yani çalışıyor.

Çözüm Kodu:
#include <stdio.h>
const int BIG = 1000000000;
const int MAXN = 2000;
const int MAXE = 20000;
const int MAXK = 200;
 
int n,e,k;
int ea[MAXE];
int eb[MAXE];
int elen[MAXE];
int d[MAXN];
int *out[MAXN];
int *len[MAXN];
int path[MAXN][MAXK];
int ei[MAXN];

int main() {
 
  FILE *fin;
 
  fin = fopen("cowjog.in", "r");
  fscanf(fin, "%d %d %d", &n, &e, &k);
  for(int i = 0; i < n; ++i){
    d[i] = 0;
  }
  for(int i = 0; i < e; ++i){
    int a,b,l;
    fscanf(fin, "%d %d %d", &b, &a, &l);
    --a; --b;
    ++d[a];
  }
  fclose(fin);
 
  out[0] = &eb[0];
  len[0] = &elen[0];
  for(int i = 1; i < n; ++i){
    out[i] = out[i-1] + d[i-1];
    len[i] = len[i-1] + d[i-1];
  }
 
  fin = fopen("cowjog.in", "r");
  fscanf(fin, "%d %d %d", &n, &e, &k);
  for(int i = 0; i < n; ++i){
    d[i] = 0;
  }
  for(int i = 0; i < e; ++i){
    int a,b,l;
    fscanf(fin, "%d %d %d", &b, &a, &l);
    --a; --b;
    out[a][d[a]] = b;
    len[a][d[a]] = l;
    ++d[a];
  }
  fclose(fin);

  path[n-1][0] = 0;
  for(int i = 1; i < k; ++i){
    path[n-1][i] = BIG;
  }
 
  for(int i = n-2; i >= 0; --i){
    for(int j = 0; j < d[i]; ++j){
      ei[j] = 0;
    }
    for(int j = 0; j < k; ++j){
      int best_m = 0;
      int best_d = BIG;
      for(int m = 0; m < d[i]; ++m){
               if(len[i][m] + path[out[i][m]][ei[m]] < best_d) {
                 best_m = m;
                 best_d = len[i][m] + path[out[i][m]][ei[m]];
               }
      }
      path[i][j] = best_d;
      ++ei[best_m];
    }
  }
 
  FILE *fout = fopen("cowjog.out", "w");
  for(int i = 0; i < k; ++i){
    fprintf(fout, "%d\n", (path[0][i] == BIG) ? -1 : path[0][i]);
  }
  fclose(fout);
  return(0);
}
Here is a concise solution that France's Louis Jachiet thinks might be easier to understand:
#include <stdio.h>
#include <algorithm>
#include <vector>
 
using namespace std;
 
int nb_paturages, nb_chemins, nb_itineraires;
vector<int> plus_court[1001];
vector<int> suiv      [1001];
vector<int> poids     [1001];
 
int main() {
    freopen("cowjog.in","r",stdin);
    freopen("cowjog.out","w",stdout);
    scanf( "%d %d %d", &nb_paturages, &nb_chemins, &nb_itineraires);
    // making the reverse graph
    for (int chem = 0; chem < nb_chemins ; chem++) {
        int dep, arr, pds;
        scanf ("%d %d %d", &dep, &arr, &pds);
        suiv [arr].push_back (dep);
        poids[arr].push_back (pds);
    }
    plus_court[1].push_back (0);
    for (int pat = 1; pat <= nb_paturages ; pat++) {
        sort (plus_court[pat].begin(), plus_court[pat].end());
        // exploring the current node for all  the shortest path
        for (int id = 0; id < plus_court[pat].size() &&
                                                             id < nb_itineraires; id++) {
            int tps = plus_court[pat][id];
            for (int id1 = 0; id1 < suiv[pat].size() ; id1++)
                plus_court[suiv[pat][id1]].push_back (tps + poids[pat][id1]);
        }
        // printing all the shortest path
        if (pat == nb_paturages)
            for (int id = 0; id < nb_itineraires ; id++)
                if (id < plus_court[pat].size())
                    printf ("%d\n", plus_court[pat][id]);
                            else
                    printf ("-1\n");
            plus_court[pat].clear();
    }

    return 0;
}

2 Ekim 2014 Perşembe

Kayak



Kış olimpiyatlarındaki kayak parkuru M x N lik (1 <= M,N <= 500) bir arazide belirlenmiştir. Her birim kare 0 .. 1,000,000,000 arasında bir yüksekliğe sahiptir.

Bazı kareler parkur yolu olarak seçilmiştir. Kış olimpiyatı organizatörleri parkur boyunca bir zorluk seviyesi (D) olması konusunda anlaşırlar. Bu şekilde bir ineğin kayarken bir kareden diğerine geçebilmesi için aralarındaki yükseklik D yi aşamayacak şekilde olmaktadır. İnek kayarken sadece güney, kuzey, doğu ve batı yönündeki komşu birim karelere gidebilmektedir.

PROBLEM ADI: ccski

GİRDİ ŞEKLİ:

* Satır 1: M ve N sayıları.

* Satır 2..1+M: Her satır N tane yükseklik içermektedir.

* Satır 2+M..1+2M: Her satır toplam N tane olmak üzere 0 ya da 1 değerlerini içermektedir. Bu değerler parkurda gidilmesi gereken yolları göstermektedir.


ÖRNEK GİRDİ (dosya ccski.in):

3 5
20 21 18 99 5
19 22 20 16 26
18 17 40 60 80
1 0 0 0 1
0 0 0 0 0
0 0 0 0 1

GİRDİ AÇIKLAMASI:

Parkur 3 x 5 lik bir arazide tanımlanmıştır. Sol ve sağ üst, sağ alt gidilmesi gereken yerleri göstermektedir.

ÇIKTI ŞEKLİ:

* Satır 1: Zorluk seviyesi (Gidilmesi gereken tüm yerlere ulaşabilecek şekilde en küçük D).

ÖRNEK ÇIKTI (dosya ccski.out):

21

ÇIKTI AÇIKLAMASI:

Eğer D = 21, 3 yere de birbirinden gidilebilir. Eğer D < 21 ise, sağ üstteki noktaya diğer iki yerden varılamaz.




Çözüm Metni :

Reachable(X) diye bir fonksiyon tanımlayalım ki bu fonksiyon bize tüm gidilmesi gereken yerlere gidilebilecek derecede olan X değerinin doğru olup olmadığını versin. Bu sayede farklı X değerleri kullanıp D değerini bulabiliriz. 0 .. 1000000000 arasında tüm X değerleri yerine ikili arama yapıp D değerini elde edebiliriz.
Dmin=0, Dmax=1000000000
while Dmin < Dmax
    X = (Dmin + Dmax) / 2
    if Reachable(X)
        Dmax = X
    else 
        Dmin = X + 1
D = Dmin
Reachable fonksiyonu üstüne bir de gidilmesi gereken noktalar arasındaki yolları belirlemek için bir algoritmaya ihtiyacımız var. Aradaki yükseklik farklı D olacak şekilde belirlemek için DFS ya da BFS kullanabiliriz. Ancak DFS bazı girdilerde çok uzun dallanmalara sebebiyet vereceği için BFS ile bunu belirlemek daha iyi olacaktır.
Her Reachable fonksiyonu çağrılması O(NM) çözüm karmaşıklığına denk gelir. İkili arama fonksiyonu da O(log R) çözüm karmaşıklığındadır. (R 0..1,000,000,000 arasındadır). Toplam çözüm karmaşıklığı O(MN log R) dir.

Soru Linki : http://usaco.org/index.php?page=viewproblem2&cpid=380
Çözüm Kodu :  http://usaco.org/current/data/sol_ccski.html



1 Ekim 2014 Çarşamba

Lopov

LOPOV

Ülkedeki güç ekonomik şartlar ve hükümetin tarımsal desteği kesmesi Mirko'yu mesleğini değiştirmeye iter, artık bir hırsızdır.Elmas çalma işindedir.

Bir depoda N tane elmas parçası , ve her elmasın Mi
ağırlığı ve Vi değeri vardır.
Mirko'nun ise K tane torbası ve her torbanın Ci maksimum kapasitesi vardır.
Bütün çaldıklarını bu torbada taşıyacaktır fakat elmaslara zarar gelmemesi için her torbada yalnız bir elmas taşıma hakkı vardır.

Mirko'nun çalabileceği toplam maksimum elmas değerini bulunuz.

GİRDİ

İlk satırda iki sayı, N ve K (1 ≤ N, K ≤ 300 000).

Ardından gelen N satırda ikişer sayı vardır, Mi ve Vi (1 ≤ Mi, Vi≤ 1 000 000).

Geri kalan K satırda bir sayı, Ci (1 ≤ Ci ≤ 100 000 000).

Girdideki tüm sayılar pozitiftir.

ÇIKTI

Tek satırda Mirko'nun taşıyabiliceği maksimum toplam elmas değeri.
Dataların %50'sinde N ve K 5000'i aşmıyacaktır.

Örnek Girdi-Çıktılar
girdi
2 1
5 10
100 100
11
çıktı
10

girdi
3 2
1 65
5 23
2 99
10
2
çıktı
164



Çözüm:

Soruyu çözerken bulmak istediğimiz şey, her bir çanta için kendi ağırlığına eşit veya kendi ağırlığından küçük ağırlığı olan ve en büyük değere sahip elması bulmak. Bunun için de çantaları küçükten büyüğe, elmasları da ağırlığına göre küçükten büyüğe sıralıyoruz.

Sonra 1'den N'e doğru her bir çanta için sıradaki işlemleri yapacağız:

1- O çantanın içine sığabilecek ağırlıktaki tüm elmasların değerlerini max heap'e atacağız (Eğer daha önce atılmamışsa).
2- Sonra heap'ten ilk elemanı alarak o çantanın içine koyarak heap'ten çıkartırız.
3- Çantaya koyduğumuz değeri toplama ekleriz.

Bu işlemi en büyük çanta için de yaptığımızda dolabilecek olan bütün çantalar optimum şekilde dolmuş olur ve sonuca ulaşmış oluruz.



Putnik

PUTNIK

Traveling Salesman problemini duymuşsunuzdur. Eğer duymuşsanız o problemin NP-hard olduğunu bilirsiniz çünkü iyi bir çözüm bulmak zordur.Pekala, bu soru ünlü problemin az rastlanan bir versiyonudur! Az rastlanması temel olarak 'çözülebilmesi'nden gelir.

Postacımız N tane şehri her birini tam olarak sadece bir kez dolaşmakla görevlidir.Şehirler 1,2,3...N olarak adlandırılır. Elimizde her şehirden birbirine giden yolların ne kadar sürdüğünü belirten bir tablo vardır. Postacı, mükemmel bir insan olduğundan, elindeki tablodan yola çıkarak öyle bir yol haritası oluşturmak ister ki toplam şehirleri dolaşma süresi minimum olsun.

Fakat herşey bu kadar kolay değildir. Postacının bir takıntısı vardır. O da şudur, her hangi bir K. şehir için kendinden önce gelen K-1 tane şehrin hepsini ya K'ya gitmeden önce dolaşmış, yada aynı şekilde hepsini K'ya gittikten sonra dolaşıcak olmalıdır.Başka bir deyişle, eğer K'dan küçük numaralı bir şehri K'ya gitmeden önce dolaşmışsa, K'ya gitmeden önce 1...K-1 şehirlerinin hepsini dolaşmış olması gerekmektedir.

Bu şartlara uyarak, postacının istediği şehirden başladığı ve istediği şehirde bitirdiği, bütün şehirleri dolaşmış olduğu minimum süreyi bulunuz.

GİRDİ

ilk satırda N (2 ≤ N ≤ 1500)
alt satırda NxN'lik bir tablo, i'inci satırdaki şehir ile j'inci sütundaki şehir arasındaki süreyi gösterir.

ÇIKTI

Tek satırda Minimum süre

ÖRNEKLER
girdi

3

0 5 2

5 0 4

2 4 0

çıktı

7

girdi

4

0 15 7 8

15 0 16 9

7 16 0 12

8 9 12 0

çıktı

31

Birinci girdideki çözümün şehir sıralaması : 2,1,3 veya 3,1,2
İkinci girdideki çözümün şehir sıralaması : 3, 1, 2, 4 veya 4, 2, 1, 3.

ÇÖZÜM
Postacının takıntısını giderecek tüm sıralamalara şu yolla ulaşabiliriz. İlk olarak 1. şehir sıralamaya eklenir sonra 2. şehir sıralamanın sağına veya soluna konulur, bu işlem N. şehire kadar devam eder ve bu yolla elde edilen her sıralama Postacının takıntısına uygundur.Artık soru dinamik programlama ile çözülebilir.Elde ettiğimiz sıralamaları listenin sağındaki ve solundaki şehir ile adlandıracağız.Bu iki şehiri bilmemiz demek bir sonraki eklenecek şehri bilmemiz demektir.Neden ? Çünkü o sıralamaya en son eklediğimiz şehir o sıranın ya solunda ya da sağında bulunmak zorundadır.Böylece ekliyceğimiz şehirin numarası onun bir fazlası olacaktır.Bu noktada ekleyeceğimiz şehir için sağa veya sola ekleme olmak üzere iki ihtimal vardır,Önceki bulduğumuz dinamik değerler ile, sağına veya soluna koyduğumuzda oluşucak minimum süreleri yeni dinamik değerler olarak bulabiliriz.Böyle ilerleyerek bütün şehirleri dolaştığımız en kısa süreyi dinamik dizi üzerinden buluruz.
O(N 2 ).

Soru: http://www.hsin.hr/coci/contest2_tasks.pdf
Girdi-Cikti: http://www.hsin.hr/coci/contest2_testdata.zip
İngilizce Çözüm: http://www.hsin.hr/coci/contest2_solutions.zip