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

hdu 3502 bfs+狀態壓縮dp

編輯:C++入門知識

hdu 3502 bfs+狀態壓縮dp


 

題意是給你n*m的矩陣 每個單位有一個數,-1表示不能走 》=0表示有有多少個能量能獲得 問從左上角到右下角能獲得的做大能量值(走一步消耗1單位能量)

思路: 先bfs求出所有線之間的最短距離(當然 有用的只有有能量值的點和起點,終點) 然後狀態壓縮dp 找到最大能量值 這裡有幾個注意的地方

狀態盡量從1開始 減少數組的空間(爆了一次) 其次是bfs是只搜有能量的點 其它都差不多;

 

 

#include
#include
#include
#include
using namespace std;

#define INF 0x3f3f3f3f

int map[300][300],dis[25][25],mark[300][300],leap[300][300];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int coord[25][3],dp[1<<18][20],n,m;
struct node
{
    int x,y;
    int step;
}a,b;
int min(int a,int b)
{
    return a<b?a:b;
}
int bfs(int k)
{
    int i;
    a.x=coord[k][1];
    a.y=coord[k][2];
    a.step=0;
    queue<node>q;
    memset(mark,0,sizeof(mark));
    mark[a.x][a.y]=1;
    q.push(a);
    while(!q.empty())
    {
        b=q.front();
        q.pop();
        for(i=0;i<4;i++)
        {
            a.x=b.x+dir[i][0];
            a.y=b.y+dir[i][1];
            a.step=b.step+1;
            if(a.x<=0||a.x>n||a.y<=0||a.y>m) continue;
            if(map[a.x][a.y]==-1) continue;
            if(mark[a.x][a.y]==0)
            {
                mark[a.x][a.y]=1;
                 dis[k][leap[a.x][a.y]]=dis[leap[a.x][a.y]][k]=a.step;
                q.push(a);
            }
        }
    }
    return 0;    
}
int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&m))
    {
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        {
            scanf("%d",&map[i][j]);
            leap[i][j]=-1;
        }
        if(map[1][1]==0&&(n>1||m>1)) {printf("you loss!\n");continue;}
        else if(n==1&&m==1) {printf("%d\n",map[1][1]);continue;}
        int t=-1;
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        {
            if(map[i][j]>0)
            {
                coord[++t][1]=i;
                coord[t][2]=j;
                leap[i][j]=t;
            }
        }
        if(map[n][m]==0)
        {
            coord[++t][1]=n;
            coord[t][2]=m;
            leap[n][m]=t;
        }
        memset(dis,INF,sizeof(dis));
        for(i=0;i<t;i++)
        {
            dis[i][i]=0;
            bfs(i);
        }
        dis[t][t]=0;
        memset(dp,-1,sizeof(dp));
        dp[1][0]=map[1][1];
        int k=(1<<(t+1));
        int Max=-1;
        for(i=1;i<k;i++)
        {
            for(j=0;j<=t;j++)
            {
                if((i&(1<<j))==0) continue;
                if(dp[i][j]<0) continue;//開始少了這句超時了一次
                for(int x=0;x<=t;x++)
                {
                    if(x==j) continue;
                    if(dp[i][j]<dis[j][x]) continue;
                    if((i&(1<<x))!=0) continue;
                    dp[i|(1<<x)][x]=max(dp[i|(1<<x)][x],dp[i][j]-dis[x][j]+map[coord[x][1]][coord[x][2]]);
                    Max=max(Max,dp[i|(1<<x)][x]-dis[x][t]);
                    //printf("^^^  %d\n",Max);
                }
            }
        }
        if(Max<0) printf("you loss!\n");
        else printf("%d\n",Max);
    }
    return 0;
}

 

 

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