hdu 5418 Victor and World(floyd+상압 dp)
제목:
1부터 시작해서 모든 점을 거쳐 최종적으로 1로 돌아가는 데 필요한 최소값을 요구한다.
해결:
이것은 비교적 고전적인 여행사 문제로 이전에 비슷한 것을 한 적이 있다.먼저 플로이드로 모든 점 사이의 최단로를 구하세요.그리고 상태로 압축하여 16자리 한 명당 1은 이미 지나갔음을 표시하고 0은 지나지 않았다는 것을 표시하며 직접 위치로 연산하여 모든 상태를 표시한다.pp[st][j] 상태는 st이고 마지막으로 걷는 것은 j점의 최소값이다.이 경우 상태 이동 방정식은 dp[st|(1<(j - 1)][j]=min(dp[st|(1< (j - 1)][j], dp[st][i]+d[i][j]) 216∗n개 상태, n종이 이동하기 때문에 복잡도는 O(216?nn)
my code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20;
const int INF = 0x3f3f3f3f;
int d[N][N];
int dp[1<<N][N];
int n, m;
void floyd() {
for(int i = 1; i <= n; i++) d[i][i] = 0;
for(int k = 1; k <= n; k++) {
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
}
int tsp() {
memset(dp,INF,sizeof(dp));
dp[1][1] = 0;
int end = (1<<n) - 1;
for (int st=1; st <=end; st++)
for(int i=1; i <= n; i++)
for(int j=1; j <= n; j++) {
if (i == j) continue;
if ((1 << (i-1)) & st == 0 || (1 << (j-1) & st == 1)) continue;
if (dp[st][i] == INF) continue;
dp[st|(1<<(j-1))][j]=min(dp[st|(1<<(j-1))][j],dp[st][i]+d[i][j]);
}
int ans = INF;
for (int i = 1; i <= n; i++)
ans=min(ans, dp[end][i]+d[i][1]);
return ans;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
memset(d, INF, sizeof(d));
int u, v, val;
for(int i = 0; i < m; i++) {
scanf("%d%d%d", &u, &v, &val);
d[u][v] = min(d[u][v], val);
d[v][u] = min(d[v][u], val);
}
floyd();
printf("%d
", tsp());
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[HDU] 4089 활성화 확률 DPdp[i][j]를 모두 i개인의 대기열인 Tomato가 j위 서버가 마비될 확률로 역추를 사용하면 우리는 상태 이동 방정식을 얻을 수 있다. i == 1 : dp[1][1] = dp[1][1] * p1 + dp[1]...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.