程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu 4568 Hunter bfs建圖+TSP狀壓DP

hdu 4568 Hunter bfs建圖+TSP狀壓DP

編輯:C++入門知識

想AC的人請跳過這一段。。。

題目應該都能讀懂。但是個人覺得這題出的很爛,意思太模糊了。

首先,進出次數只能是一次!!這個居然在題目中沒有明確說明,讓我在當時看到題目的時候無從下手。

因為我想到了這幾個數據:

1 1 1                   1 9 1                  -1 -1 -1

-1-1-1                     9 9 9                  -1 1 -1

1 1 1                       1 9 1                  -1 -1 -1

6個寶藏                  四個角是寶藏      中間是寶藏

第一個數據如果進出2次,就可以拿走全部的6個寶藏,也符合題目的“bring out all treasures he can take”。

即使是規定了進出只能一次,那這個數據又該輸出什麼?( if nothing James can get, please output 0)

第二個數據如果進出4次,就可以最快的拿走全部寶藏。

第三個數據唯一的寶藏拿不走。

不過,這題的測試數據中並沒有上面的例子。

以上為個人YY

 


以下為題解:

進出一次,找到所有能找到的寶藏,裸的TSP問題。

首先選一個自己喜歡的算法建圖。將整個邊界理解成一個點,找到每兩個寶藏之間的最短距離和每個寶藏的離邊界點的最短距離。

然後就是TSP,狀態壓縮DP解。

 


 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int n,m,tre;
int ID[205][205];
int map[205][205];
int dis[20][20];
bool vis[205][205];
int dp[1<<16][20];
struct node
{
    int x,y;
}t[20];
struct node2
{
    int x,y,dis;
    bool operator <(const node2 & f) const
    {
        return dis>f.dis;
    }
};
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
bool isok(int x,int y)
{
    return x>=0&&x<n&&y>=0&&y<m&&map[x][y]!=-1;
}
void bfs(int k)
{
    priority_queue<node2> Q;
    int v[20]={0};
    memset(vis,0,sizeof(vis));
    node2 f,r;
    r.x=t[k].x;
    r.y=t[k].y;
    r.dis=0;
    Q.push(r);
    v[k]=1;
    vis[r.x][r.y]=1;
    int tot=1,id;
    while(!Q.empty())
    {
        f=Q.top(); Q.pop();
        if(!v[0]&&(f.x==0||f.y==0||f.x==n-1||f.y==m-1))
        {
            v[0]=1;
            dis[k][0]=f.dis;
            dis[0][k]=f.dis+map[t[k].x][t[k].y];
            tot++;
            if(tot==tre+1) return;
        }
        id=ID[f.x][f.y];
        if(id&&!v[id])
        {
            tot++;
            v[id]=1;
            dis[k][id]=f.dis;
            if(tot==tre+1) return;
        }
        for(int d=0;d<4;d++)
        {
            r.x=f.x+dx[d];
            r.y=f.y+dy[d];
            r.dis=f.dis+map[r.x][r.y];
            if(isok(r.x,r.y)&&!vis[r.x][r.y])
            {
                vis[r.x][r.y]=1;
                Q.push(r);
            }
        }
    }
}
int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        memset(ID,0,sizeof(ID));
        memset(dis,0x3f,sizeof(dis));
        memset(dp,0x3f,sizeof(dp));
        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",&tre);
        for(int i=1;i<=tre;i++)
        {
            scanf("%d%d",&t[i].x,&t[i].y);
            ID[t[i].x][t[i].y]=i;
        }
        for(int i=1;i<=tre;i++)
            {
                bfs(i);
            }
        dis[0][0]=0;
        if(!tre) {printf("0");continue;}

        for(int i=0;i<=tre;i++)
        {
            dp[1<<i][i]=dis[0][i];
        }
        int end=(1<<(tre+1));
        for(int i=0;i<end;i++)
        {
            for(int j=0;j<=tre;j++)
            {
                if((i>>j)&1)
                {
                    for(int k=0;k<=tre;k++)
                    {
                        if((i>>k)&1)
                        {
                            dp[i][j]=min(dp[i][j],dp[i&(~(1<<j))][k]+dis[k][j]);
                        }
                    }
                }
            }
        }
        printf("%d\n",dp[end-1][0]);
    }
    return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved