【USACO 2013 1月金组】Island Travels

时间限制: 1 Sec  内存限制: 128 MB

题目描述

FJ组织它的奶牛去海边度假。海边有N(N<=15)个岛屿,这些岛屿分布在一个R*C(1<=R,C<=50)的区域中。一个岛屿是一个由‘X’组成连通块。有的格子标有‘S’,表示浅水区,有的格子标有‘.’,表示深水区。奶牛贝西可以从任意一个岛屿出发,它要遍历所有的岛屿,它可以游泳通过浅水区。求贝西游泳的最短的距离——每一次经过的S的个数之和。同一个‘S’可以经过多次,但是每次都要记入距离。

输入

输入:

第一行R,C。

接下来R行C列,每个字符可能是‘X’,‘S’,‘.’。

输出

贝西游泳的最短距离。

样例输入

5 4
XX.S
.S..
SXSS
S.SX
..SX

样例输出

3

考试的时候遭遇这题绝对对我算不上什么好回忆,我想了各种可能但是仿佛都失败了,最后没办法我开始写暴力(我真的还没有学过状压dp啊,并且我就一直是那种典型的思维弱渣)。

正解是这样的,说说我的理解。

因为相邻岛屿之间互相穿梭是不需要距离的,所以把它们全部打包。

于是在这些包之间可以做最短路,也可以搜索求路径,反正就是要求出来。

之后状压dp

用一个15位的二进制数来表示当前的状态(最右边位表示第一个包是否访问过了,1表示访问过)

例如

001010101010101

表示第1,3,5,7,9,11,13个岛屿已经访问过了,

于是这个状态可以由以下状态转移过来

000010101010101,001000101010101,001010001010101,001010100010101,001010101000101,001010101010001,001010101010100

用一个二维数组表示状态Dp[state][i]表示达到state状态的最小答案

state表示当前的访问情况(如上例),i表示当前在此状态中的第i个小岛上,即有1的一个位置

于是Dp[state][i]=min(Dp[ state' ][i], Dp[state][j]+way[j][i]);

我在码题的时候尝试了两种求最短路的方案:

一是对每一个包Bfs,直接求完它到其他所有点的最小距离(包括要经过'X'),

二是先对每一个包Bfd,只求它只经过‘S’能到达的所有点的最小距离,再跑floyd,

发现,,时间并没有变化,,真是有趣了,

话说我考试的时候就只差最后的Dp,我当时写的Dfs,嗯结果得了54分,时间卡飞。嗯我认了,该撒。

纯Bfs找路径:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<climits>
#include<queue>
#include<cstring>
using namespace std;
const int Max=50;
struct node{int x,y,cnt;node(){}node(int a,int b,int c){x=a,y=b,cnt=c;}
}P[20];
struct qu{int cnt;node pos[260];
}Pl[20];
int R,C,Ans=INT_MAX,all,flag;
int Dp[(1<<15)+5][20];
int dd[4][2]={{0,1},{-1,0},{1,0},{0,-1}};
int have[Max+5][Max+5],way[20][20];
char map[Max+5][Max+5];
bool vis[Max+5][Max+5],use[Max+5];
void getint(int &num){char c;int flag=1;num=0;while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}num*=flag;
}
bool haveway(int x,int y){if(map[x-1][y]=='S'||map[x][y-1]=='S'||map[x+1][y]=='S'||map[x][y+1]=='S')return 1;return 0;
}
queue<node>Q;
void together(int x,int y){++flag;vis[x][y]=1;P[flag]=node(x,y,0);have[x][y]=flag;Q.push(P[flag]);int xx,yy;if(haveway(x,y))    Pl[flag].pos[++Pl[flag].cnt]=node(x,y,0);while(!Q.empty()){node tmp=Q.front();Q.pop();have[tmp.x][tmp.y]=flag;for(int i=0; i<4; ++i){xx=tmp.x+dd[i][0];yy=tmp.y+dd[i][1];if(!vis[xx][yy]&&map[xx][yy]=='X'){vis[xx][yy]=1;have[xx][yy]=flag;Q.push(node(xx,yy,0));if(haveway(xx,yy))Pl[flag].pos[++Pl[flag].cnt]=node(xx,yy,0);}}}
}
int Bfs(int s){queue<node>q;int xx,yy;for(int i=1; i<=Pl[s].cnt; ++i)q.push(Pl[s].pos[i]),vis[Pl[s].pos[i].x][Pl[s].pos[i].y]=1;while(!q.empty()){node tmp=q.front();q.pop();for(int i=0; i<4; ++i){xx=tmp.x+dd[i][0];yy=tmp.y+dd[i][1];if(!vis[xx][yy]&&map[xx][yy]=='X'&&have[xx][yy]!=have[P[s].x][P[s].y]){vis[xx][yy]=1;way[s][have[xx][yy]]=min(tmp.cnt,way[s][have[xx][yy]]);q.push(node(xx,yy,tmp.cnt));}else if(!vis[xx][yy]&&map[xx][yy]=='S'){vis[xx][yy]=1;q.push(node(xx,yy,tmp.cnt+1));}}}return 0;
}
int main(){//freopen("island.in","r",stdin);//freopen("island.out","w",stdout);getint(R),getint(C);for(int i=1; i<=R; ++i)scanf("%s",map[i]+1);for(int i=1; i<=R; ++i)for(int j=1; j<=C; ++j)if(map[i][j]=='X'&&!have[i][j])together(i,j);memset(way,0x3f,sizeof(way));for(int i=1; i<=flag; ++i){memset(vis,0,sizeof(vis));Bfs(i);}memset(Dp,0x3f,sizeof(Dp));for(int i=0; i<flag; ++i)Dp[(1<<i)][i]=0;int N=(1<<flag);for(int i=0; i<N; ++i)for(int j=0; j<flag; ++j)if((i>>j)&1)for(int k=0; k<flag; ++k)Dp[i|(1<<k)][k]=min(Dp[i|(1<<k)][k],Dp[i][j]+way[j+1][k+1]);Ans=0x3f3f3f3f;for(int i=0; i<flag; ++i)Ans=min(Ans,Dp[(1<<flag)-1][i]);printf("%d\n",Ans);return 0;
}

Bfs+flpyd:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<climits>
#include<queue>
#include<cstring>
using namespace std;
const int Max=50;
struct node{int x,y,cnt;node(){}node(int a,int b,int c){x=a,y=b,cnt=c;}
}P[20];
struct qu{int cnt;node pos[260];
}Pl[20];
int R,C,Ans=INT_MAX,all,flag;
int Dp[(1<<15)+5][20];
int dd[4][2]={{0,1},{-1,0},{1,0},{0,-1}};
int have[Max+5][Max+5],way[20][20];
char map[Max+5][Max+5];
bool vis[Max+5][Max+5],use[Max+5];
void getint(int &num){char c;int flag=1;num=0;while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}num*=flag;
}
bool haveway(int x,int y){if(map[x-1][y]=='S'||map[x][y-1]=='S'||map[x+1][y]=='S'||map[x][y+1]=='S')return 1;return 0;
}
queue<node>Q;
void together(int x,int y){++flag;vis[x][y]=1;P[flag]=node(x,y,0);have[x][y]=flag;Q.push(P[flag]);int xx,yy;if(haveway(x,y))    Pl[flag].pos[++Pl[flag].cnt]=node(x,y,0);while(!Q.empty()){node tmp=Q.front();Q.pop();have[tmp.x][tmp.y]=flag;for(int i=0; i<4; ++i){xx=tmp.x+dd[i][0];yy=tmp.y+dd[i][1];if(!vis[xx][yy]&&map[xx][yy]=='X'){vis[xx][yy]=1;have[xx][yy]=flag;Q.push(node(xx,yy,0));if(haveway(xx,yy))Pl[flag].pos[++Pl[flag].cnt]=node(xx,yy,0);}}}
}
int Bfs(int s){queue<node>q;int xx,yy;for(int i=1; i<=Pl[s].cnt; ++i)q.push(Pl[s].pos[i]),vis[Pl[s].pos[i].x][Pl[s].pos[i].y]=1;while(!q.empty()){node tmp=q.front();q.pop();for(int i=0; i<4; ++i){xx=tmp.x+dd[i][0];yy=tmp.y+dd[i][1];if(!vis[xx][yy]&&map[xx][yy]=='X'&&have[xx][yy]!=have[P[s].x][P[s].y]){vis[xx][yy]=1;way[s][have[xx][yy]]=min(tmp.cnt,way[s][have[xx][yy]]);}else if(!vis[xx][yy]&&map[xx][yy]=='S'){vis[xx][yy]=1;q.push(node(xx,yy,tmp.cnt+1));}}}return 0;
}
int main(){//freopen("island.in","r",stdin);//freopen("island.out","w",stdout);getint(R),getint(C);for(int i=1; i<=R; ++i)scanf("%s",map[i]+1);for(int i=1; i<=R; ++i)for(int j=1; j<=C; ++j)if(map[i][j]=='X'&&!have[i][j])together(i,j);memset(way,0x3f,sizeof(way));for(int i=1; i<=flag; ++i){way[i][i]=0;memset(vis,0,sizeof(vis));Bfs(i);}for(int k=1; k<=flag; ++k)for(int i=1; i<=flag; ++i)for(int j=1; j<=flag; ++j)if(way[i][k]+way[j][k]<way[i][j])way[i][j]=way[i][k]+way[j][k];memset(Dp,0x3f,sizeof(Dp));for(int i=0; i<flag; ++i)Dp[(1<<i)][i]=0;int N=(1<<flag);for(int i=0; i<N; ++i)for(int j=0; j<flag; ++j)if((i>>j)&1)for(int k=0; k<flag; ++k)Dp[i|(1<<k)][k]=min(Dp[i|(1<<k)][k],Dp[i][j]+way[j+1][k+1]);Ans=0x3f3f3f3f;for(int i=0; i<flag; ++i)Ans=min(Ans,Dp[(1<<flag)-1][i]);printf("%d\n",Ans);return 0;
}

#USACO#Island Travels相关推荐

  1. 【BZOJ3049】Island Travels,SPFA预处理+状态压缩DP

    传送门(权限题) 3049: [Usaco2013 Jan]Island Travels Time Limit: 10 Sec Memory Limit: 128 MB Submit: 84 Solv ...

  2. USACO2013 island travels

    题意:一个R行C列的矩阵,'X'表示地,'S'表示浅水,'.'表示不能走的深水.连通的X视为一个岛(不超过15个).现在要走完所有岛,求最少的踩在浅水格子的次数. 题解:岛屿不超过15个,明显的暗示可 ...

  3. (Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

    下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinej ...

  4. 算法竞赛入门经典+挑战编程+USACO

    下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinej ...

  5. usaco Shaping Regions

    这就是usaco 前面的windows area的变形. /* ID:jinbo wu TASK:rect1 LANG:C++ */ #include<iostream> #include ...

  6. usaco Postal Vans(dp)

    是哈密顿回路,然后...就不知道怎么写了 ,以前写过类似的不过情况没这么多也没这么复 usaco training 6.1.1 Postal Vans 题解 标签: usaco training题解d ...

  7. usaco Beef McNuggets

    这两天贼烦,ccf炸了,还有一个烦心事.哎我都不知道自己能不能坚持下去了.马上期末考了.这段时间还是抓紧时间复习吧同时刷usaco的节奏要跟以前一样了,毕竟课少了. 题解: 只要你知道以下的数论结论, ...

  8. usaco前两章小结

    usaco 暑假老师有推荐做但是那个题目太长了,而且·大部分都是废话做起来特别慢,而且当时自己基本上什么都不懂,太难了所以看了题解做了两题就放弃了. 转眼就上学了,因为想学习acm所以就胡乱找题做但是 ...

  9. usaco ★Fractions to Decimals 分数化小数

    ★Fractions to Decimals 分数化小数 写一个程序,输入一个形如 N/D 的分数(N 是分子,D 是分母),输出它的小数形式. 如果小数有循环节的话,把循环节放在一对圆括号中.例如, ...

最新文章

  1. 1196: 数星星(二)(结构体专题)_福利:最新导数6大专题!高分段提分有困扰?听北大状元漫谈提分...
  2. 深度解析容器化技术在广发证券交易系统的应用
  3. 常说SCI论文有多少篇,那你知道SCI是什么吗?
  4. Sublime Text 3 全套快捷键及功能介绍
  5. Android下的数据储存方式(三)
  6. 5种全局ID生成方式、优缺点及改进方案
  7. mac terminal ssh client shuttle 免输密码
  8. Unity3D开发的赛车单机小游戏详细介绍(附有游戏下载链接)
  9. Python笔记(二)——python调用C/C++模块
  10. 很吊炸天的Xcode插件,你想要的这都有
  11. IntelliJ IDEA开发工具插件GsonFormat插件安装使用
  12. 哈夫曼编码原理分析及代码实现(有注释)
  13. 防御DDoS攻击的五种方法
  14. Google Earth Engine(GEE)统计制图
  15. 树莓派开机启动chromium浏览器
  16. 他们都说springboot是懒人神器,你觉得呢?
  17. 一位大牛对学IT的忠告
  18. 英科学家用扫描技术成功读取大脑记忆
  19. 什么是setInterval/setTimeout?
  20. break跳出两个嵌套的for循环

热门文章

  1. HoloLens2之路-配置文件(一)
  2. 电子商务网站用户行为分析及服务推荐
  3. c++plus_6th_第4章
  4. undefined is not a function
  5. linux文件无法写入
  6. tomcat连接池的配置与使用
  7. c语言中signal函数详细说明--举例
  8. Python之私有属性和私有方法
  9. 论文画图——eps格式的图
  10. Mac-如何在任意文件夹下打开终端