[스탠너 트리] HDOJ 3311 Dig The Wells
문제 풀이 방향: DP 과정이 1차원 증가하면 물을 마실 수 있는지 없는지를 나타낸다. 스탠나 나무를 만들고 DP를 만든다.
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 1009
#define maxm 10005
#define eps 1e-7
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head
struct Edge
{
int v, w;
Edge *next;
}*H[maxn], *edges, E[maxm];
struct node
{
int x, y, k;
node() {}
node(int x, int y, int k) : x(x), y(y), k(k) {}
};
queue<node> q;
int c[maxn];
int p[maxn];
int dp[maxn];
int d[maxn][1 << 6][2];
int in[maxn][1 << 6][2];
int n, m, m2, o;
void addedges(int u, int v, int w)
{
edges->v = v;
edges->w = w;
edges->next = H[u];
H[u] = edges++;
}
void init()
{
edges = E;
memset(H, 0, sizeof H);
memset(p, 0, sizeof p);
memset(d, INF, sizeof d);
memset(dp, INF, sizeof dp);
}
void read()
{
int u, v, w;
for(int i = 1; i <= n + m; i++) scanf("%d", &c[i]);
while(m2--) {
scanf("%d%d%d", &u, &v, &w);
addedges(u, v, w);
addedges(v, u, w);
}
o = 1 << n;
for(int i = 1; i <= n; i++) {
p[i] = 1 << i - 1;
d[i][p[i]][0] = 0;
d[i][p[i]][1] = c[i];
}
}
void spfa()
{
while(!q.empty()) {
int x = q.front().x, y = q.front().y, k = q.front().k;
q.pop(), in[x][y][k] = false;
for(Edge *e = H[x]; e; e = e->next) {
int v = e->v, w = e->w;
if(!k) {
if(d[v][y | p[v]][0] > d[x][y][0] + w) {
d[v][y | p[v]][0] = d[x][y][0] + w;
if(!in[v][y | p[v]][0]) {
in[v][y | p[v]][0] = true;
q.push(node(v, y | p[v], 0));
}
}
if(d[v][y | p[v]][1] > d[x][y][0] + w + c[v]) {
d[v][y | p[v]][1] = d[x][y][0] + w + c[v];
if(!in[v][y | p[v]][1]) {
in[v][y | p[v]][1] = true;
q.push(node(v, y | p[v], 1));
}
}
}
else {
if(d[v][y | p[v]][1] > d[x][y][1] + w) {
d[v][y | p[v]][1] = d[x][y][1] + w;
if(!in[v][y | p[v]][1]) {
in[v][y | p[v]][1] = true;
q.push(node(v, y | p[v], 1));
}
}
}
}
}
}
void work()
{
for(int y = 0; y < o; y++) {
for(int x = 1; x <= n + m; x++) {
for(int i = (y - 1) & y; i; i = (i - 1) & y) {
d[x][y][0] = min(d[x][y][0], d[x][y - i | p[x]][0] + d[x][i | p[x]][0]);
d[x][y][1] = min(d[x][y][1], d[x][y - i | p[x]][1] + d[x][i | p[x]][0]);
d[x][y][1] = min(d[x][y][1], d[x][y - i | p[x]][0] + d[x][i | p[x]][1]);
// d[x][y][1] = min(d[x][y][1], d[x][y - i | p[x]][1] + d[x][i | p[x]][1]);
}
if(d[x][y][0] < INF) q.push(node(x, y, 0)), in[x][y][0] = true;
if(d[x][y][1] < INF) q.push(node(x, y, 1)), in[x][y][1] = true;
}
spfa();
}
for(int i = 0; i < o; i++)
for(int j = 1; j <= n + m; j++)
dp[i] = min(dp[i], d[j][i][1]);
for(int i = 0; i < o; i++)
for(int j = (i - 1) & i; j; j = (j - 1) & i)
dp[i] = min(dp[i], dp[i - j] + dp[j]);
printf("%d
", dp[o - 1]);
}
int main()
{
while(scanf("%d%d%d", &n, &m, &m2)!=EOF) {
init();
read();
work();
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
hdu3709 (디지털 dp)A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. When a pivot is pla...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.