【题解】 P3070 [USACO13JAN]岛游记Island Travels

题面有点坑,翻译内容中没有指明n的范围,通过观察原题面得到$n \leq 15$并大致猜测这是一个状态压缩dp

最小生成树显然不可行,可以举例说明存在某种情况某边要经过两次或更多

对于任意一个岛屿$i$到任意一个岛屿$j$的最短距离显然是固定的,每个岛域之间的距离(不经过其他岛屿)可以用bfs预处理出来,初始状态只要将这个岛屿全部坐标位置全部入队即可

得到了任意两个岛屿之间的直接距离后(当然存在部分岛屿不可互达),在$ n \leq 15$时可以直接用$floyd$求解

现在得到任意两个节点之间的最短距离,显然直接dfs复杂度任然爆炸,dfs求解的复杂度是$O(n!)$

考虑状态压缩dp,设$S$为当前节点是否经过的状态集合,$v$为当前停留的节点,显然有$f(S,v)=min\{ f(S‘,u)+dis(u,v)\}$其中$S‘$中$v$为未达,很明显对于任意一个状态他最多转移$n$个状态

得到时间复杂度为$O(2^nn)$的状压

```
//2019/7/24->Riko->AtNCU->luoguP3070
#include<bits/stdc++.h>
template <typename T> inline void smin (T& x, T y) { if (x > y) x = y;}
//Believing heart is your power
using namespace std;
int getch () {
    int ch = getchar();
    return (ch == ‘.‘ or ch == ‘S‘ or ch == ‘X‘) ? ch : getch();
}

const int N = 55;
struct Point {
    int x, y;
    Point (int x, int y) : x(x), y(y) {}
};
struct Len {
    int x, y, l;
    Len (int x, int y, int l) : x(x), y(y), l(l) {}
};
int r, c, n, ind;
int type[N][N], idx[N][N], len[N][N], vis[N][N], hasgone[N];
int f[(1<<15)+64][16], Mx[4] = {0, 0, 1, -1}, My[4] = {1, -1, 0, 0};
queue <Point> Find, Save[N];
queue <Len> Que;

void Getpoints (int x, int y) {
    Find.push(Point(x, y)); Save[ind].push(Point(x, y));
    while (!Find.empty()) {
        Point tem = Find.front(); Find.pop();
        for (int i = 0; i < 4; ++i) {
            int Nx = tem.x+Mx[i];
            int Ny = tem.y+My[i];
            if (idx[Nx][Ny]) continue;
            if (type[Nx][Ny] != 1) continue;
            idx[Nx][Ny] = ind;
            Find.push(Point(Nx, Ny));
            Save[ind].push(Point(Nx, Ny));
        }
    }
}
void Getlen (int id) {
    while (!Save[id].empty()) {
        Point tem = Save[id].front(); Save[id].pop();
        Que.push(Len(tem.x, tem.y, 0)); vis[tem.x][tem.y] = true;
    }
    while (!Que.empty()) {
        Len tem = Que.front(); Que.pop();
        for (int i = 0; i < 4; ++i) {
            int Nx = tem.x+Mx[i];
            int Ny = tem.y+My[i];
            if (!type[Nx][Ny] or vis[Nx][Ny]) continue;
            if (idx[Nx][Ny]) { smin(len[id][idx[Nx][Ny]], tem.l); continue;}
            vis[Nx][Ny] = true;
            Que.push(Len(Nx, Ny, tem.l+1));
        }
    }
}
void work () {
    memset(f, 0x3f, sizeof(f));
    for (int i = 1; i <= ind; ++i) {f[(1<<(i-1))][i] = 0;}
    for (int x = 1; x < (1<<ind); ++x) {
        for (int u = 1; u <= ind; ++u) {
            if (!x&(1<<(u-1))) continue;
            for (int v = 1; v <= ind; ++v) {
                if (x&(1<<(v-1))) continue;
                smin(f[x|(1<<(v-1))][v], f[x][u]+len[u][v]);
            }
        }
    }
    int ans = INT_MAX;
    for (int i = 1; i <= ind; ++i) { smin(ans, f[(1<<ind)-1][i]);}
    printf("%d", ans);
}
void prepare () {
    scanf("%d %d", &r, &c);
    for (int i = 1; i <= r; ++i) {
        for (int j = 1; j <= c; ++j) {
            int ch = getch();
            if (ch == ‘X‘) type[i][j] = 1;
            if (ch == ‘S‘) type[i][j] = 2;
        }
    }
    for (int i = 1; i <= r; ++i) {
        for (int j = 1; j <= c; ++j) {
            if (!idx[i][j] and type[i][j] == 1) {
                idx[i][j] = ++ind;
                Getpoints(i, j);
            }
        }
    }        //prepare for the distance
    memset(len, 0x3f, sizeof(len));
    for (int i = 1; i <= r; ++i) {
        for (int j = 1; j <= c; ++j) {
            if (idx[i][j] and !hasgone[idx[i][j]]) {
                memset(vis, 0, sizeof(vis));
                hasgone[idx[i][j]] = true;
                Getlen(idx[i][j]);
            }
        }
    }        //Get the cloest distance
    for (int i = 1; i <= ind; ++i) {
        for (int j = i+1; j <= ind; ++j) {
            for (int k = i+1; k < j; ++k) {
                smin(len[i][j], len[i][k]+len[k][j]);
                len[j][i] = len[i][j];
            }
        }
    }          //floyd Part
    work();
} int main () { prepare();}
```

原文地址:https://www.cnblogs.com/NHDR233/p/11246717.html

时间: 2024-08-30 05:23:19

【题解】 P3070 [USACO13JAN]岛游记Island Travels的相关文章

洛谷P3070 [USACO13JAN]岛游记Island Travels

P3070 [USACO13JAN]岛游记Island Travels 题目描述 Farmer John has taken the cows to a vacation out on the ocean! The cows are living on N (1 <= N <= 15) islands, which are located on an R x C grid (1 <= R, C <= 50). An island is a maximal connected gro

题解——逃离僵尸岛(BFS+最短路+虚拟节点)

题解--逃离僵尸岛(BFS+最短路+虚拟节点) 一道很巧妙的最短路问题,细节也要注意 题面 Description 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入.由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市.换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险. 小a住在1号城市,国际

【浮*光】#noip# 知识点总结

[零. 序言] ------头文件 #include<cstdio>    #include<iostream>    #include<cstring>    #include<string>    #include<algorithm>    #include<cmath>    #include<set>    #include<vector>    #include<map>    #inc

国家二字码对照表

中文国家名 英文国家名 大洲 二位简码 法属南部领地 French Southern Territories Europe TF 夏威夷 Hawaii North America HW 阿拉斯加 Alaska North America AK 新西兰属土岛屿 New Zealand Islands Territories Oceania XL 加罗林群岛 Caroline Islands Asia XK 巴利阿里群岛 Balearic Islands Europe XJ 马德拉群岛 Madeir

推荐电影 梦工厂经典电影列表 1996-2012

梦工厂 百科名片 梦工厂海报 梦工厂(DreamWorks SKG)是美国排名前十位的一家电影洗印.制作和发行公司,同时也是一家电视游戏,电视节目制作公司.它制作发行的电影有超过10部票房收入超过1亿美元. 概述 电影公司始建于1994年10月,三位创始人分别是史蒂文·斯皮尔伯格(代表DreamWorks SKG中的"S"),杰弗瑞·卡森伯格(代表DreamWorks SKG中的"K")和大卫·格芬(代表DreamWorks SKG中的"G").

新概念英语第三册1-20课(转)

Lesson 1  A Puma at large 逃遁的美洲狮 1.美洲狮是大的,Pumas are large,猫一样的 cat-like动物 animals它们被发现 which are found在美洲. in America. 美洲狮是一种大型猫科动物Pumas are large, cat-like animals它们被发现在美洲. which are found in America. 美洲狮一种生活在美洲的大型猫科动物, 2.当时-报告When reports提交到伦敦动物园 c

上海各行政区域地铁站分布数量

首先是地铁站代号 ST_NO,ST_NAME,ST_NAME_EN,LINE_NO,X,Y,TRANSFER_TAG,SERIAL_NO,ST_HORIZONTAL 0111,莘庄,Xinzhuang ,1,201,771,换乘站,28,地面 0112,外环路,Waihuanlu ,1,224,738,普通站,27,地面 0113,莲花路,Lianhua Road ,1,243,721,普通站,26,地面 0114,锦江乐园,Jinjiang Park ,1,270,753,普通站,25,地面

关于图算法 &amp; 图分析的基础知识概览

网址:https://learning.oreilly.com/library/view/graph-algorithms-/9781492060116/ 你肯定没有读过这本书,因为这本书的发布日期是2019年5月.本文会覆盖该书的大部分内容,读完这篇,你能够了解图算法的基本概念.关于此书,作为市面上为数不多的面向数据科学应用的图算法书籍,写的比较全面系统和易懂.当然,书在细节上的提高空间还有很多.今天内容很多,坐稳~ 目录 图算法 & 图分析 图基础知识 连通图与非连通图 未加权图与加权图 有

POJ3422:Kaka&#39;s Matrix Travels——题解

http://poj.org/problem?id=3422 题目大意: 从左上角走到右下角,中途取数(数>=0),然后该点的数变为0,求走k的总价值和最大值. —————————————————————————————— 最大值?但是我们只会最小费用流啊…… 但是数是>=0的啊,所以…… 我们拆点,中间连一条容量为1费用为当前值负值的边,再连一条容量为k-1费用0的边. 这样就一定会先走前一条边啦! 然后向下向右连一条容量为k费用0的边. 源点到左上角连一条容量为k-1费用0的边. 右下角到