hdu4568

来源:互联网 发布:单片机晶振电容选择 编辑:程序博客网 时间:2024/06/18 08:39

题目链接hdu4568Hunter

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2165 Accepted Submission(s): 679

Problem Description
  One day, a hunter named James went to a mysterious area to find the treasures. James wanted to research the area and brought all treasures that he could.
  The area can be represented as a N*M rectangle. Any points of the rectangle is a number means the cost of research it,-1 means James can’t cross it, James can start at any place out of the rectangle, and explore point next by next. He will move in the rectangle and bring out all treasures he can take. Of course, he will end at any border to go out of rectangle(James will research every point at anytime he cross because he can’t remember whether the point are researched or not).
  Now give you a map of the area, you must calculate the least cost that James bring out all treasures he can take(one point up to only one treasure).Also, if nothing James can get, please output 0.

这里写图片描述

Input
  The input consists of T test cases. The number of test cases T is given in the first line of the input. Each test case begins with a line containing 2 integers N M , (1<=N,M<=200), that represents the rectangle. Each of the following N lines contains M numbers(0~9),represent the cost of each point. Next is K(1<=K<=13),and next K lines, each line contains 2 integers x y means the position of the treasures, x means row and start from 0, y means column start from 0 too.

Output
  For each test case, you should output only a number means the minimum cost.

Sample Input
2
3 3
3 2 3
5 4 3
1 4 2
1
1 1
3 3
3 2 3
5 4 3
1 4 2
2
1 1
2 2

Sample Output
8
11

Source
2013 ACM-ICPC长沙赛区全国邀请赛——题目重现

题意:给定一个n*m的棋盘,每一个格子有一个值,代表经过这个格子的花费,给出K(K<=13)个宝藏点的坐标,求从棋盘的任意一个边进入棋盘,经过所有的宝藏点后再走出,求最小的话费,如果知道了每个宝藏之间的最短路径(花费),就是裸的旅行商问题了,所以, 我们前面工作就是找出每个宝藏点到其他所有宝藏点的最短距离了,我们设宝藏图外面为0点,然后K个宝藏点,为1-K,枚举K个宝藏点,算出每个宝藏点到其余宝藏点的最短花费,放到数组d[][]中,然后套了一下旅行商模板

#include <iostream>#include <queue>#include <stdio.h>#include <string.h>const int maxn=550,inf=0x3f3f3f3f;using namespace std;struct point{    int x,y,cost;    point(){;}    point(int xx,int yy,int Cost)    {        x=xx;        y=yy;        cost=Cost;    }    friend bool operator<(const point a,const point b)    {        return a.cost>b.cost;    }}kc[30];int dx[4]={0,1,0,-1};int dy[4]={-1,0,1,0};int n,m,k;int map[maxn][maxn],d[30][30],D[maxn][maxn];int isc[maxn][maxn];///宝藏标记图bool vis[maxn][maxn],visd[30];void bfs(point tep,int I){    priority_queue<point>que;///用优先队列来保存,就不用去比较是不是最小的花费了,    que.push(tep);    int tot=0;    memset(visd,false,sizeof(visd));    memset(vis,false,sizeof(vis));    vis[tep.x][tep.y]=true;    visd[I]=true;    int nx,ny;    while(!que.empty())    {        point now=que.top();        que.pop();        vis[now.x][now.y]=true;        nx=now.x,ny=now.y;        if(!visd[0]&&(nx==1||nx==n||ny==1||ny==m))        {            tot++;            visd[0]=true;            d[I][0]=now.cost;///宝藏到边界距离            d[0][I]=now.cost+map[tep.x][tep.y];///边界到宝藏距离比宝藏到边界距离大一个宝藏自己的距离           if(tot==k)           return;        }        int ii=isc[now.x][now.y];        if(ii>0&&!visd[ii])///若果是宝藏点        {            tot++;            visd[ii]=true;            d[I][ii]=now.cost;            if(tot==k)///找到k+1个宝藏点就退出                return;        }        for(int j=0;j<4;j++)        {            nx=now.x+dx[j];            ny=now.y+dy[j];            if(nx<1||nx>n||ny<1||ny>m)                continue;            if(!vis[nx][ny]&&map[nx][ny]!=-1)            {                vis[nx][ny]=true;                que.push(point(nx,ny,now.cost+map[nx][ny]));            }        }    }}const int K=14;int dp[1<<K][K];int main(){    int T;    int cx,cy;    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",&map[i][j]);       }       scanf("%d",&k);       for(int i=0;i<=k;i++)       {           for(int j=0;j<=k;j++)           {               if(i==j)                d[i][j]=0;               else                d[i][j]=inf;           }       }       memset(isc,0,sizeof(isc));       for(int i=1;i<=k;i++)       {           scanf("%d%d",&cx,&cy);           cx++,cy++;           isc[cx][cy]=i;           kc[i].x=cx;           kc[i].y=cy;           kc[i].cost=0;       }       for(int i=1;i<=k;i++)            bfs(kc[i],i);        ///旅行商模板。。。。        memset(dp,inf,sizeof(dp));        dp[(1<<(k+1))-1][0]=0;        for(int s=(1<<(k+1))-1;s>=0;s--){            for(int pp=0;pp<k+1;pp++){                for(int qq=0;qq<k+1;qq++){                    if(!(s&(1<<qq)))                    dp[s][pp]=min(dp[s][pp],dp[s|(1<<qq)][qq]+d[pp][qq]);                }            }        }        if(dp[0][0]>=inf)        puts("0");        else        printf("%d\n",dp[0][0]);    }    return 0;}
原创粉丝点击