1. 程式人生 > >HDU 3001 三進制狀壓DP

HDU 3001 三進制狀壓DP

name ring flag main div while hdu style emp

N個城市,M條道路,每條道路有其經過的代價,每一個城市最多能夠到達兩次,求走全然部城市最小代價,起點隨意。

三進制狀壓。存儲每一個狀態下每一個城市經過的次數。


轉移方程: dp[i+b[k]][k]=Min(dp[i+b[k]][k],dp[i][j]+dis[j][k]);


#include "stdio.h"
#include "string.h"

const int inf=0x3f3f3f3f;

int b[15],mark[60010][15],dp[60010][15],dis[15][15];
int Min(int a,int b)
{
    if (a<b) return a;
    else return b;
}
int main()
{
    int i,j,n,m,k,temp,ans,flag;

    b[0]=1;
    for (i=1; i<=10; i++)
        b[i]=b[i-1]*3;

    for (i=0; i<b[10]; i++) // 記錄每種狀態下,每一個城市經過的情況。

{ temp=i; for (j=0; j<10; j++) { mark[i][j]=temp%3; temp/=3; } } while (scanf("%d%d",&n,&m)!=EOF) { memset(dis,inf,sizeof(dis)); memset(dp,inf,sizeof(dp)); while (m--) { scanf("%d%d%d",&i,&j,&k); i--; j--; if (dis[i][j]>k) dis[i][j]=dis[j][i]=k; } for (i=0; i<n; i++) dp[b[i]][i]=0; ans=inf; for (i=0; i<b[n]; i++) { flag=1; for (j=0; j<n; j++) { if (mark[i][j]==0) flag=0; if (dp[i][j]==inf) continue; for (k=0; k<n; k++) if (k!=j && mark[i][k]<2 && dis[j][k]!=inf) dp[i+b[k]][k]=Min(dp[i+b[k]][k],dp[i][j]+dis[j][k]); } if (flag==1) for (j=0; j<n; j++) ans=Min(ans,dp[i][j]); } if (ans==inf) printf("-1\n"); else printf("%d\n",ans); } return 0; }



HDU 3001 三進制狀壓DP