1. 程式人生 > >ACM 海賊王之偉大航路(深搜剪枝)

ACM 海賊王之偉大航路(深搜剪枝)

“我是要成為海賊王的男人!”

路飛他們偉大航路行程的起點是羅格鎮,終點是拉夫德魯(那裡藏匿著“唯一的大祕寶”——ONE PIECE)。而航程中間,則是各式各樣的島嶼。

因為偉大航路上的氣候十分異常,所以來往任意兩個島嶼之間的時間差別很大,從A島到B島可能需要1天,而從B島到A島則可能需要1年。當然,任意兩個島之間的航行時間雖然差別很大,但都是已知的。

現在假設路飛一行從羅格鎮(起點)出發,遍歷偉大航路中間所有的島嶼(但是已經經過的島嶼不能再次經過),最後到達拉夫德魯(終點)。假設他們在島上不作任何的停留,請問,他們最少需要花費多少時間才能到達終點?

輸入輸入資料包含多行。
第一行包含一個整數N(2 < N ≤ 16),代表偉大航路上一共有N個島嶼(包含起點的羅格鎮和終點的拉夫德魯)。其中,起點的編號為1,終點的編號為N。
之後的N行每一行包含N個整數,其中,第i(1 ≤ i ≤ N)行的第j(1 ≤ j ≤ N)個整數代表從第i個島嶼出發到第j個島嶼需要的時間t(0 < t < 10000)。第i行第i個整數為0。輸出輸出為一個整數,代表路飛一行從起點遍歷所有中間島嶼(不重複)之後到達終點所需要的最少的時間。樣例輸入

樣例輸入1:
4
0 10 20 999
5 0 90 30
99 50 0 10
999 1 2 0

樣例輸入2:
5
0 18 13 98 8
89 0 45 78 43 
22 38 0 96 12
68 19 29 0 52
95 83 21 24 0

樣例輸出

樣例輸出1:
100

樣例輸出2:
137
題目如上

如題,第一想法是深搜(據說可以用dp,但還沒想出來),寫了一版深搜,結果超時了,意料之中,下面附程式碼以及剪枝。

#include<cstdio>
#include<string.h>
#include<stdlib.h>
#include<math.h>
const int inf = 0x3f3f3f3f;
int step;
int minstep;
int a[16][16];
int book[15];
int postion[20];
int n;
int npostion[15][1<<15];
int po;
void dfs(int cur,int qc)
{
    if(cur+2==n)
    {
        step+=a[qc][n-1];
        if(step<minstep)
            minstep=step;
        step-=a[qc][n-1];
        return;
    }
    for(int i=1; i<n-1; i++)
    {
        if(!book[i])// has been through
        {
            if(step>=minstep)
                continue;
            if((npostion[i][po+postion[i-1]]<=step+a[qc][i]))
                continue;
            po+=postion[i-1];
            step+=a[qc][i];
            npostion[i][po]=step;
            book[i]=1;
            dfs(cur+1,i);
            po-=postion[i-1];
            book[i]=0;
            step-=a[qc][i];
        }
    }
}
int main()
{
    for(int i=0; i<14; i++)
        postion[i]=1<<i;
    while (~scanf("%d",&n))
    {
        po=0;
        step=0;
        minstep=1e17;
        memset(npostion,inf,sizeof(npostion));
        memset(a,0,sizeof(a));
        memset(book,0,sizeof(book));
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                scanf("%d",&a[i][j]);
        dfs(0,0);
        printf("%d\n",minstep