hdu 4511 - 샤 오 밍 시리즈 - 여자친 구 의 시련 (AC 자동 동기 + dp)
Problem Description 이 드디어 겨울방학 이 되 었 습 니 다. 샤 오 밍 은 여자 친구 와 함께 영 화 를 보 러 가 려 고 합 니 다.이날 여자 친 구 는 샤 오 밍 에 게 시련 을 주 려 고 했다. 샤 오 밍 이 출발 준 비 를 하고 있 을 때 여자 친 구 는 그 에 게 영화관 에서 그 를 기다 리 고 있다 고 말 했다. 샤 오 밍 이 오 는 노선 은 반드시 주어진 규칙 을 만족 시 켜 야 한다. 1. 샤 오 밍 이 있 는 위치 가 1 번 점 이 고 여자 친구 가 있 는 위치 가 n 번 점 이 라면 그들 사이 에 n - 2 개의 점 이 걸 을 수 있다 고 가정 했다.샤 오 밍 은 갈 때마다 현재 지점 보다 번호 가 큰 위치 에 만 갈 수 있다.2. 샤 오 밍 이 올 때 일정한 순서에 따라 어떤 곳 을 지나 갈 수 없다.예 를 들 어 여자친 구가 샤 오 밍 에 게 1 - > 2 - > 3 을 거치 지 말 라 고 하면 샤 오 밍 이 올 때 걸 어 온 경 로 는 1 - > 2 - > 3 부분 을 포함 할 수 없 지만 1 - > 3 또는 1 - > 2 는 모두 가능 하 다. 이런 제한 경 로 는 여러 가지 가 있 을 수 있다.이것 은 샤 오 밍 을 매우 골 치 아 프 게 했 는데, 지금 그 는 문 제 를 너 에 게 맡 겼 다.특히 하나, 둘, 셋 이라는 세 점 의 공선 이 있 는데 도 샤 오 밍 이 1 에서 3 까지 직접 이 어 졌 다 면 이런 상황 은 샤 오 밍 이 2 를 거 쳤 다 고 생각 하지 않 는 다 는 것 이다.지금 샤 오 밍 은 가장 짧 은 길 을 걸 어서 여자 친 구 를 빨리 만 나 고 싶 고 여자 친구 의 규정 을 깨 고 싶 지 않 습 니 다. 샤 오 밍 이 이 문 제 를 해결 하 는 데 도움 을 줄 수 있 습 니까?
Input 입력 은 여러 그룹의 사례 를 포함 합 니 다. 각 그룹의 사례 는 먼저 두 개의 정수 n 과 m 를 포함 합 니 다. 그 중에서 n 은 n 개의 점 이 있 고 샤 오 밍 은 1 번 점 에 있 으 며 여자 친 구 는 n 번 점 에 있 고 m 는 샤 오 밍 의 여자 친 구 를 대표 하여 m 의 요구 가 있 습 니 다.다음 n 줄 마다 2 개의 정수 x 와 y (x 와 y 는 모두 int 범위) 를 입력 하여 이 n 개의 점 의 위치 (점 의 번 호 는 1 에서 n) 를 대표 합 니 다.그 다음 에 m 개의 요구 입 니 다. 각각 2 줄 을 요구 합 니 다. 먼저 한 줄 은 k 입 니 다. 이 요 구 는 k 개의 점 과 관련 이 있 음 을 나타 내 고 그 다음 에 순서대로 제 시 된 k 개의 점 번 호 는 샤 오 밍 이 k1 - > k2 - > k3... - > ki 라 는 순서 의 경 로 를 의미 합 니 다.n 과 m 가 0 일 때 입력 이 끝 납 니 다.
[Technical Specification] 2 <= n <= 50 1 <= m <= 100 2 <= k <= 5
Output 은 모든 사례 에 대해 요 구 를 만족 시 키 는 가장 짧 은 경로 가 존재 한다 면 이 가장 짧 은 경 로 를 출력 하 십시오. 결 과 는 두 개의 작은 수 를 유지 합 니 다.그렇지 않 으 면 출력 하 십시오. "도달 할 수 없습니다!"(인용 부 호 는 출력 할 필요 가 없다).
Sample Input
3 1 1 1 2 1 3 1 2 1 2
2 1 0 0 1 1 2 1 2
5 3 0 0 5 3 1 2 1 22 5 21 3 1 2 3 2 4 5 2 1 5
0 0
Sample Output
2.00 Can not be reached! 21.65
Source 2013 텐 센트 프로 그래 밍 마라톤 1 차 전 2 차 전 (3 월 22 일)
Recommend liuyiding | We have carefully selected several similar problems for you: 5209 5208 5207 5206 5205
일부 경로 가 존재 하지 않 는 다 는 것 을 알려 드 립 니 다. 이것 은 분명 한 힌트 입 니 다. 바로 자동 동기 dp 입 니 다. dp [i] [j] 는 자동 동기 노드 i 를 표시 하고 j 를 누 를 때 가장 짧 은 경로 입 니 다. 처음에 제 순환 방식 이 틀 렸 을 수도 있 습 니 다. 나중에 바 꾸 면 됩 니 다. 좌 표를 직접 double 로 읽 는 것 이 좋 겠 습 니 다.
/************************************************************************* > File Name: hdu4511.cpp > Author: ALex > Mail: [email protected] > Created Time: 2015 04 16 18 24 11 ************************************************************************/
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <vector>
using namespace std;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;
const int MAX_NODE = 510;
int n;
double dp[MAX_NODE][55];
struct node
{
double x, y;
}point[55];
double dist(node a, node b)
{
double x = (a.x - b.x);
double y = (a.y - b.y);
return sqrt(x * x + y * y);
}
struct AC_Automation
{
int next[MAX_NODE][55];
int fail[MAX_NODE];
int end[MAX_NODE];
int root, L;
int newnode()
{
for (int i = 0; i < n; ++i)
{
next[L][i] = -1;
}
end[L++] = 0;
return L - 1;
}
void init ()
{
L = 0;
root = newnode();
}
void Build_Trie (vector <int> buf)
{
int now = root;
int len = buf.size();
for (int i = 0; i < len; ++i)
{
if (next[now][buf[i]] == -1)
{
next[now][buf[i]] = newnode();
}
now = next[now][buf[i]];
}
end[now] = 1;
}
void Build_AC ()
{
queue <int> qu;
fail[root] = root;
for (int i = 0; i < n; ++i)
{
if (next[root][i] == -1)
{
next[root][i] = root;
}
else
{
fail[next[root][i]] = root;
qu.push (next[root][i]);
}
}
while (!qu.empty())
{
int now = qu.front();
qu.pop();
if (end[fail[now]])
{
end[now] = 1;
}
for (int i = 0; i < n; ++i)
{
if (next[now][i] == -1)
{
next[now][i] = next[fail[now]][i];
}
else
{
fail[next[now][i]] = next[fail[now]][i];
qu.push(next[now][i]);
}
}
}
}
void solve()
{
for (int i = 0; i < L; ++i)
{
for (int j = 0; j < n; ++j)
{
dp[i][j] = (1LL << 60);
}
}
dp[next[root][0]][0] = 0.0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < L; ++j)
{
if (dp[j][i] < (1LL << 60))
{
for (int k = i + 1; k < n; ++k)
{
int nxt = next[j][k];
if (end[nxt])
{
continue;
}
dp[nxt][k] = min(dp[nxt][k], dp[j][i] + dist(point[k], point[i]));
}
}
}
}
double ans = (1LL << 60);
for (int i = 0; i < L; ++i)
{
if (end[i] == 0)
{
ans = min(ans, dp[i][n - 1]);
}
}
if (ans == (1LL << 60))
{
printf("Can not be reached!
");
}
else
{
printf("%.2f
", ans);
}
}
}AC;
vector <int> buf;
int main()
{
int m;
while (~scanf("%d%d", &n, &m))
{
if (!n && !m)
{
break;
}
AC.init();
int tmp;
for (int i = 0; i < n; ++i)
{
scanf("%lf%lf", &point[i].x, &point[i].y);
}
for (int i = 1; i <= m; ++i)
{
int k;
buf.clear();
scanf("%d", &k);
while (k--)
{
scanf("%d", &tmp);
--tmp;
buf.push_back(tmp);
}
AC.Build_Trie(buf);
}
AC.Build_AC();
AC.solve();
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【경쟁 프로 전형적인 90문】008의 해설(python)의 해설 기사입니다. 해설의 이미지를 봐도 모르는 (이해력이 부족한) 것이 많이 있었으므로, 나중에 다시 풀었을 때에 확인할 수 있도록 정리했습니다. ※순차적으로, 모든 문제의 해설 기사를 들어갈 예정입니다. 문자열...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.