您的位置:首页 > 其它

HDU 4568【最短路+状压DP】

2015-09-03 16:56 561 查看
应该算是比较裸的最短路和状压DP。。。感觉之前看到的题都是DP。。因为想的问题都一样。

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

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

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
#define maxn 211
#define maxdp 10110
#define inf 0x3f3f3f3f
int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: