BZOJ 3045 전화선 폭력
사고방식: T를 생각하면 접미사 수조를 쓰거나 최적화를 덧붙이면 바로 A가 된다.
CODE:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 50010
#define MAXE 5000010
#define BASE 2333
#define INF 0x3f3f3f3f
using namespace std;
unsigned long long power[20];
struct Complex{
char s[12];
int _id,num[10];
unsigned long long hash,_hash,sorting;
bool operator <(const Complex &a)const {
return sorting < a.sorting;
}
void Read(int p) {
_id = p;
scanf("%s",s + 1);
hash = _hash = 0;
for(int i = 1; i <= 10; ++i) {
hash = hash * BASE + s[i];
++num[s[i] - '0'];
}
for(int i = 0; i <= 9; ++i)
_hash = _hash * BASE + num[i];
}
int LCP(const Complex &a)const {
for(int i = 1;; ++i)
if(s[i] != a.s[i])
return i - 1;
return 0;
}
}src[MAX];
int cnt;
int cost[10];
void Pretreatment()
{
power[0] = 1;
for(int i = 1; i <= 15; ++i)
power[i] = power[i - 1] * BASE;
}
int head[MAX],total;
int next[MAXE],aim[MAXE],length[MAXE];
inline void Add(int x,int y,int len)
{
next[++total] = head[x];
aim[total] = y;
length[total] = len;
head[x] = total;
}
inline void AddEdge(int l,int r)
{
for(int i = l; i <= r; ++i)
for(int j = i + 1; j <= r; ++j) {
int lcp = src[i].LCP(src[j]);
Add(src[i]._id,src[j]._id,cost[lcp]);
Add(src[j]._id,src[i]._id,cost[lcp]);
}
}
inline void AddEdge(int l,int r,bool flag)
{
for(int i = l; i <= r; ++i)
for(int j = i + 1; j <= r; ++j)
if(src[i]._hash == src[j]._hash) {
int lcp = src[i].LCP(src[j]);
Add(src[i]._id,src[j]._id,cost[lcp]);
Add(src[j]._id,src[i]._id,cost[lcp]);
}
}
int SPFA()
{
static int f[MAX];
static bool v[MAX];
static queue<int> q;
memset(f,0x3f,sizeof(f));
f[1] = 0;
q.push(1);
while(!q.empty()) {
int x = q.front(); q.pop();
v[x] = false;
for(int i = head[x]; i; i = next[i])
if(f[aim[i]] > f[x] + length[i]) {
f[aim[i]] = f[x] + length[i];
if(!v[aim[i]]) {
v[aim[i]] = true;
q.push(aim[i]);
}
}
}
return f[cnt] == INF ? -1:f[cnt];
}
int main()
{
Pretreatment();
cin >> cnt;
for(int i = 0; i <= 9; ++i)
scanf("%d",&cost[i]);
for(int i = 1; i <= cnt; ++i)
src[i].Read(i);
for(int i = 1; i <= 10; ++i) {
for(int j = 1; j <= cnt; ++j)
src[j].sorting = src[j].hash - power[10 - i] * src[j].s[i];
sort(src + 1,src + cnt + 1);
unsigned long long now = src[1].sorting;
int last = 1;
for(int j = 1; j <= cnt; ++j)
if(src[j].sorting != now) {
AddEdge(last,j - 1);
last = j;
now = src[j].sorting;
}
AddEdge(last,cnt);
}
for(int i = 1; i <= 10; ++i)
for(int j = i + 1; j <= 10; ++j) {
for(int k = 1; k <= cnt; ++k)
src[k].sorting = src[k].hash - power[10 - i] * src[k].s[i] - power[10 - j] * src[k].s[j];
sort(src + 1,src + cnt + 1);
unsigned long long now = src[1].sorting;
int last = 1;
for(int k = 1; k <= cnt; ++k)
if(src[k].sorting != now) {
AddEdge(last,k - 1,false);
last = k;
now = src[k].sorting;
}
AddEdge(last,cnt,false);
}
cout << SPFA() << endl;
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Wunder Fund Round 2016(Div 1 + Div 2 combined) B] [폭력 욕심] Guess the Permutation 전체 배열 a[i] [j]=min(p[i],ptime limit per test memory limit per test input standard input standard output Bob has a permutation of integers from 1 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.