不得不说状态压缩是个很神奇的东西,学习了一天终于稍微学懂了,这个问题,
首先,旅行商问题状态转移方程 dp[i][j] 表示经过第i个点,第j个状态
dp[i][j] = min (dp[i][j],dp[prei][j - (1<<i)] + cost);
这只是第一道。。。还会待续的
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int M = 232;
const int inf = 1e10;
int dis[M*M],n,m;
int map[M][M],dp[20][1<<16],user[M*M],tre[M][M],go[M][M],cost[M],vis[M*M];
struct Node{
int i,dis;
Node(){};
Node (int a,int b){
i = a;dis = b;
}
bool operator < (const Node& a)const{
return dis > a.dis;
}
};
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,1,-1};
void dij(int st,int pos){
priority_queue<Node> Q;
Q.push(Node(st,0));
memset(vis,0,sizeof(vis));
for(int i=0;i<=n*m;i++)
dis[i] = inf;
dis[st] = 0;
Node it;
while(!Q.empty()){
it = Q.top();Q.pop();
int u = it.i ;
if(vis[u])continue;
vis[u] = 1;
int x = u /m,y = u%m;
if(tre[x][y] != -1) go[pos][tre[x][y]] = dis[u];
if(x==0||y==0||x==n-1||y==m-1){
cost[pos] = min(cost[pos],dis[u]);
}
for(int d=0;d<4;d++)
{
int nx = dx[d]+x;
int ny = dy[d]+y;
if(map[nx][ny] == -1)continue;
if(nx < 0||nx >= n||ny < 0 || ny >=m)continue;
int uu = nx * m+ny;
if(dis[uu] > dis[u]+map[nx][ny]){
dis[uu] = dis[u] + map[nx][ny];
Q.push(Node(uu,dis[uu]));
}
}
}
}
int main()
{
int k,x,y;
int T;
scanf("%d",&T);
while(T--) {
memset(tre,-1,sizeof(tre));
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&map[i][j]);
scanf("%d",&k);
memset(go,63,sizeof(go));
for(int i=0;i<k;i++){
scanf("%d%d",&x,&y);
//go[i][i] = 0;
tre[x][y] = i;
user[i] = x * m + y;
}
for(int i=0;i<k;i++){
go[i][i] = 0 ;
cost[i] = inf;
dij(user[i],i);
}
memset(dp,63,sizeof(dp));
for(int i=0;i<k;i++){
x = user[i] / m;
y = user[i] % m;
dp[i][1<<i] = cost[i] + map[x][y];
}
for(int j=0;j<(1<<k);j++){
for(int i=0;i<k;i++){
//if(j&(1<<i)&&j!=(1<<i))
if((j&(1<<i)) == 0) continue;
// if(dp[i][j] == inf) continue;
for(int s = 0;s<k;s++){
if((j & (1 << s)) == 0) continue;
dp[i][j] = min(dp[i][j],dp[s][j-(1<<i)]+go[s][i]);
}
}
}
int ans = inf;
for(int i=0;i<k;i++){
ans = min(dp[i][(1<<k)-1]+cost[i],ans);
}
printf("%d\n",ans);
}
}