題意:給乙個n*m的格仔,格仔中有一些數,如果是正整數則為到此格仔的花費,如果為-1表示此格仔不可到,現在給k個寶藏的地點(k<=13),求乙個人從邊界外一點進入整個棋盤,然後拿走所有能拿走的寶藏的最小花費,如果一次不能拿走所有能拿到的或者根本拿不到任何寶藏,輸出0.
解法:看到k的範圍應該想到狀態壓縮,將每個格仔都看成乙個點,再新建兩個點,乙個表示邊界外的起點,用0表示,乙個表示邊界外的終點,用n*m+1表示,然後相互建邊,建有向邊,邊權為終點格仔的花費值,(其實都不用建邊,直接跑最短路也行)然後求這k+2個點兩兩之間的最短距離,然後就化成tsp問題了,用狀壓dp可以解決。
求k+2個點兩兩之間的最短距離可以跑k+2次spfa求出,複雜度不高。
**:
#include #includeview code#include
#include
#include
#include
#include
#define mod 1000000007
using
namespace
std;
#define n 10007
int mp[304][304
];int c[304][304
];int dis[20][20
];int
n,m,k;
int d[50005
];struct
node
g[4*50005
];int head[4*50005
],tot;
int dx[4] = ;
int dy[4] = ;
int vis[50006
];struct
point
p[15
];int ok(int nx,int
ny)void addedge(int u,int v,int
w)void spfa(int
s) }
}}int dp[1
<<17][20
];int
main()
memset(head,-1,sizeof
(head));
tot = 0
;
for(i=1;i<=n;i++)
if(i == 1 || i == n || j == 1 || j == m) //
邊界 }
}scanf("%d
",&k);
p[0].x = 1, p[0].y = 0
; p[k+1].x = n,p[k+1].y = m+1
;
for(i=1;i<=k;i++)
scanf(
"%d%d
",&p[i].x,&p[i].y),p[i].x++,p[i].y++;
for(i=0;i<=k+1;i++)
}for(i=0;i
<<16);i++)
for(j=0;j<16;j++)
dp[i][j]=mod;
for(i=0;i)
dp[1<1]=dis[0][i+1
];
for(i=0;i}}
int minn=mod;
for(i=1;i<=k;i++)
minn=min(dp[(1
<1][i]+dis[i][k+1
],minn);
if(minn ==mod)
cout
<<0
<
else
cout
}return0;
}
hdu 4568 旅行商問題dp
這個題目題意描述不清,沒有說明只能進入一次。題目意思很好理解,不再重複。思路也比較好想,先計算每兩個寶藏區的最短路,和每個寶藏區到邊界的最短路,然後dp解決。在計算最短路的時候,用優先佇列優化的dijkstra演算法。在 1的處理上有些小技巧。但是!但是!我之前的思路是dp i 表示狀態i的最小co...
HDU 2544 最短路 最短路
最近複習了最短路徑的演算法,就寫了4個版本的測試。正好是模板題,就果斷a之。dijkstar版本 include include include include include include includeusing namespace std define n 110 define max 99...
hdu 2544 最短路(最短路)
time limit1000 ms memory limit32768 kb 在每年的校賽裡,所有進入決賽的同學都會獲得一件很漂亮的t shirt。但是每當我們的工作人員把上百件的衣服從商店運回到賽場的時候,卻是非常累的!所以現在他們想要尋找最短的從商店到賽場的路線,你可以幫助他們嗎?input輸入...