最近想再学学状压DP
hunter
hdu 4568
借鉴了
http://www.cnblogs.com/whatbeg/p/3962180.html
的代码
自己为温习堆优化的dijkstra 写了一个更长的
作为 第一步吧
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
#define oo 1000000007
#define i2 (i<<1)
#define i3 ((i<<1)|1)
using namespace std;
int tot,T,n,m,sz,k;
int d[50005],dis[20][20],dp[1<<17][20],a[205][205];
struct node
{
int x,y;
}p[20];
const int dx[4]={1,0,0,-1};
const int dy[4]={0,1,-1,0};
int Next[200005],to[200005],len[200005],head[50005];
void add(int x,int y,int z)
{
Next[tot]=head[x];
to[tot]=y;
len[tot]=z;
head[x]=tot++;
}
int pos[50005],hp[50005];
void put(int x)
{
hp[++sz]=x;pos[x]=sz;
int i=sz;
while (i>>1)
{
int u=hp[i],v=hp[i>>1];
if (d[u]<d[v])
swap(pos[u],pos[v]),swap(hp[i],hp[i>>1]);
else break;
i>>=1;
}
}
int get()
{
int ret=hp[1];
hp[1]=hp[sz--];
int i=1,j;
while (i2<=sz)
{
int u=hp[i2],v=hp[i3];
if (i3>sz || d[u]<d[v]) j=i2;
else j=i3;
u=hp[i],v=hp[j];
if (d[u]>d[v])
{
swap(pos[u],pos[v]);
swap(hp[i],hp[j]);
i=j;
}
else break;
}
return ret;
}
void ajust(int x)
{
int i=pos[x];
while (i>>1)
{
int u=hp[i],v=hp[i>>1];
if (d[u]<d[v])
swap(pos[u],pos[v]),swap(hp[i],hp[i>>1]);
else break;
i>>=1;
}
}
void heapdij(int st)
{
for (int i=0;i<=n*m+1;i++)
{
d[i]=oo;
pos[i]=0;
}
d[st]=0;
put(st);
while (sz)
{
int x=get();pos[x]=0;
for (int i=head[x];i!=-1;i=Next[i])
{
int y=to[i],z=len[i];
if (d[x]+z<d[y])
{
d[y]=d[x]+z;
if (!pos[y]) put(y);
else ajust(y);
}
}
}
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
if (a[i][j]==-1)
a[i][j]=oo;
}
tot=0;
memset(head,-1,sizeof(head));
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
int now=(i-1)*m+j;
for (int h=0;h<4;h++)
{
int nx=i+dx[h],ny=j+dy[h];
if (nx>=1 && nx<=n && ny>=1 && ny<=m)
{
int tmp=(nx-1)*m+ny;
add(now,tmp,a[nx][ny]);
}
}
if (i==1 || i==n || j==1 || j==m)
{
add(0,now,a[i][j]);
add(now,n*m+1,0);
}
}
scanf("%d",&k);
p[0].x=1,p[0].y=0;
p[k+1].x=n,p[k+1].y=m+1;
for (int i=1;i<=k;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
p[i].x++;p[i].y++;
}
for (int i=0;i<=k+1;i++)
{
int st=(p[i].x-1)*m+p[i].y;
sz=0;
heapdij(st);
for (int j=0;j<=k+1;j++)
{
if (i==j) continue;
int tmp=(p[j].x-1)*m+p[j].y;
dis[i][j]=d[tmp];
}
}
for (int i=0;i<(1<<16);i++)
for (int j=0;j<16;j++)
dp[i][j]=oo;
for (int i=0;i<k;i++)
dp[1<<i][i+1]=dis[0][i+1];
for (int i=0;i<(1<<k);i++)
{
for (int kk=0;kk<k;kk++)
{
if (!(i&(1<<kk))) continue;
for (int j=0;j<k;j++)
{
if (i&(1<<j)) continue;
dp[i+(1<<j)][j+1]=min(dp[i+(1<<j)][j+1],dp[i][kk+1]+dis[kk+1][j+1]);
}
}
}
int ans=oo;
for (int i=1;i<=k;i++)
ans=min(ans,dp[(1<<k)-1][i]+dis[i][k+1]);
if (ans==oo) printf("0\n");
else printf("%d\n",ans);
}
return 0;
}