HDU 4568【最短路+状压DP】

来源:互联网 发布:淘宝怎查被隐形降权 编辑:程序博客网 时间:2024/04/29 23:37

应该算是比较裸的最短路和状压DP。。。感觉之前看到的题都是DP。。因为想的问题都一样。

有一点,由于状态在转移的时候,是由哪一个点转移过来的很重要,所以并不能通过取最小值来决定从哪一个点转移来,所以每个点产生的情况都要记录。在这里错了好久。。。

恩。。这样说来应该还是蛮简单的。。。。

#include <stdio.h>#include <iostream>#include <string.h>#include <queue>using namespace std;#define maxn 211#define maxdp 10110#define inf 0x3f3f3f3fint d[14][maxn][maxn];int a[maxn][maxn];int n,m,num,flag;int vis[maxn][maxn];int visdp[14][maxdp],dp[14][maxdp];queue<pair<int,int>>que;int dx[4]={1,-1,0,0};int dy[4]={0,0,1,-1};class node{public:    int x,y;    int minn,cost;}p[14];bool check(int x,int y){    if(x<0||x>=n||y<0||y>=m) return false;    if(a[x][y]==inf) return false;    return true;}int min(int x,int y){return x<y?x:y;}int max(int x,int y){return x>y?x:y;}void SPFA(){    memset(vis,0,sizeof(vis));    for(int i=0;i<num;i++)    {        int x=p[i].x,y=p[i].y;        d[i][x][y]=0;        que.push(make_pair(x,y));        vis[x][y]=1;        while(que.size())        {            x=que.front().first,y=que.front().second;            que.pop();            vis[x][y]=0;            for(int j=0;j<4;j++)            {                int tx=x+dx[j],ty=y+dy[j];                if(check(tx,ty))                    if(d[i][x][y]+a[tx][ty]<d[i][tx][ty])                    {                        d[i][tx][ty]=d[i][x][y]+a[tx][ty];                        if(!vis[tx][ty]) que.push(make_pair(tx,ty)),vis[tx][ty]=1;                    }            }        }        p[i].minn=inf;        for(int j=0;j<m;j++)            p[i].minn=min(p[i].minn,min(d[i][0][j],d[i][n-1][j]));        for(int j=0;j<n;j++)            p[i].minn=min(p[i].minn,min(d[i][j][0],d[i][j][m-1]));        if(p[i].minn>=inf) {flag=1;break;}    }}void Tosoon(){    for(int i=0;i<num;i++)        for(int j=0;j<maxdp;j++)            dp[i][j]=inf;}void Search(){    memset(visdp,0,sizeof(visdp));    Tosoon();    int maxnum=(1<<num);    if(num==1)    {        int ans=p[0].minn*2+p[0].cost;        if(ans>=inf) cout<<0<<endl;        else cout<<ans<<endl;        return;    }    for(int i=0;i<maxnum;i++)    {        for(int j=0;j<num;j++)        {            int now=(1<<j)|i;            if(!i) dp[j][now]=p[j].minn+p[j].cost,visdp[j][now]=1;            else            {                int jj=1<<j;                if(i&jj) continue;                for(int k=0;k<num;k++)                {                    if(!visdp[k][i]||d[k][p[j].x][p[j].y]>=inf) continue;                    dp[j][now]=min(dp[j][now],dp[k][i]+d[k][p[j].x][p[j].y]);                    visdp[j][now]=1;                }            }        }    }    int ans=inf;    for(int i=0;i<num;i++)        ans=min(ans,dp[i][maxnum-1]+p[i].minn);    if(ans>=inf) {cout<<0<<endl;return;}    cout<<ans<<endl;}void init(){    for(int i=0;i<14;i++)        for(int j=0;j<maxn;j++)            for(int k=0;k<maxn;k++)                d[i][j][k]=inf;}int main(){    int T;    cin>>T;    while(T--)    {        init();        flag=0;        cin>>n>>m;        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)            {                cin>>a[i][j];                if(a[i][j]==-1) a[i][j]=inf;            }        cin>>num;        for(int i=0;i<num;i++)        {            cin>>p[i].x>>p[i].y;            p[i].cost=a[p[i].x][p[i].y];            if(p[i].cost==inf) flag=1;        }        SPFA();        if(flag){cout<<0<<endl;continue;}        Search();    }    return 0;}


0 0
原创粉丝点击