codeforces 677D
2016-07-18 20:50
232 查看
强行暴力水过……二维线段树真的长,我实在是不想写了.暴力1k左右,而二维线段树5k……
题目大意
一个N*M的网格图,每个格子有一把钥匙,上面一个权值
要求从 1到 P按顺序收集钥匙,保证 P只有一把
问收集全部钥匙的最短距离是多少
做法1:大概就是维护用纵列维护一个dis,用横列维护一个dp,用vis维护他得到的钥匙的序号,有才更新,感觉很巧妙.
状态转移方程
位置(r,c),更新dis[r][k]=min(dis[r][k],ans[r][c]+abs(c-k)),1<=k<=m。
ans[r][c]=min(ans[r][c],dis[k][c]+abs(c-r)),1<=k<=n
代码
做法2
首先大家都应该能想的o(n^4)的暴力吧,我们只不过是用二维线段树或二维树状数组优化成o(n^2*logn^2)而已,但代码量大了不少.
状态转移方程
if(pi>=i&&pj>=j)dp[i][j]=min(dp[i][j],dp[pi][pj]+pi+pj-(i+j));
if(pi>=i&&pj<=j)dp[i][j]=min(dp[i][j],dp[pi][pj]+pi-pj-(i-j));
if(pi<=i&&pj>=j)dp[i][j]=min(dp[i][j],dp[pi][pj]+pj-pi-(j-i));
if(pi<=i&&pj<=j)dp[i][j]=min(dp[i][j],dp[pi][pj]-(pi+pj)+(i+j));
代码就不贴了(我才不会告诉你是因为我没调出来)
这道题方法很多,如暴力+bfs等,在此不再赘述(毕竟蒟蒻搞不懂)
题目大意
一个N*M的网格图,每个格子有一把钥匙,上面一个权值
要求从 1到 P按顺序收集钥匙,保证 P只有一把
问收集全部钥匙的最短距离是多少
做法1:大概就是维护用纵列维护一个dis,用横列维护一个dp,用vis维护他得到的钥匙的序号,有才更新,感觉很巧妙.
状态转移方程
位置(r,c),更新dis[r][k]=min(dis[r][k],ans[r][c]+abs(c-k)),1<=k<=m。
ans[r][c]=min(ans[r][c],dis[k][c]+abs(c-r)),1<=k<=n
代码
#include <cstdio> #include <cmath> #include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; typedef pair <int,int> mk; int n,m,k,dp[305][305],vis[305][305],dis[305][305]; int t,len; vector <mk>b[300*300+10]; void readdata() { scanf("%d%d%d",&n,&m,&k); memset(dp,63,sizeof(dp)); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { scanf("%d",&t); b[t].push_back(mk(i,j)); } b[0].push_back(mk(1,1)); for (int i=0;i<=k;i++) { len=b[i].size(); for (int j=0;j<len;j++) { int r=b[i][j].first; int c=b[i][j].second; if (r==1&&c==1&&dp[r][c]==0) { dp[r][c]=1000000000; } for (t=1;t<=n;t++) { if (vis[t][c]==i) dp[r][c]=min(dp[r][c],dis[t][c]+abs(r-t)); } } for (int j=0;j<len;j++) { int r=b[i][j].first; int c=b[i][j].second; for (int t=1;t<=m;t++) { if (vis[r][t]!=i+1) { vis[r][t]=i+1; dis[r][t]=dp[r][c]+abs(c-t); } else { dis[r][t]=min(dis[r][t],dp[r][c]+abs(c-t)); } } } } cout<<dp[b[k][0].first][b[k][0].second]; } int main() { readdata(); }
做法2
首先大家都应该能想的o(n^4)的暴力吧,我们只不过是用二维线段树或二维树状数组优化成o(n^2*logn^2)而已,但代码量大了不少.
状态转移方程
if(pi>=i&&pj>=j)dp[i][j]=min(dp[i][j],dp[pi][pj]+pi+pj-(i+j));
if(pi>=i&&pj<=j)dp[i][j]=min(dp[i][j],dp[pi][pj]+pi-pj-(i-j));
if(pi<=i&&pj>=j)dp[i][j]=min(dp[i][j],dp[pi][pj]+pj-pi-(j-i));
if(pi<=i&&pj<=j)dp[i][j]=min(dp[i][j],dp[pi][pj]-(pi+pj)+(i+j));
代码就不贴了(我才不会告诉你是因为我没调出来)
这道题方法很多,如暴力+bfs等,在此不再赘述(毕竟蒟蒻搞不懂)
相关文章推荐
- 数据结构——二叉树的四种遍历方式(非递归)
- 消息队列mq的原理及实现方法
- 结构体(hdu 1236)
- 包含min函数的栈
- python错误之mission parentheses in call to 'print'
- 大菲波数<hdoj1715>
- 逃离迷宫
- AsyncTask异步任务类
- Java学习一:一些基本的语句
- HDU 1548 A strange lift
- 数据结构中的逻辑结构简介
- jQuery中:first和:first-child的区别
- 关于kubernetes 的 服务发现
- PHP超级全局数组$_FILES
- IO多路复用之select
- 动态存储分配
- httpd基本配置示例
- 线段树各种小练习
- Lenovo K29 笔记本经常没声音解决方案Hotkey[gevu18ww].exe
- 【转载】气象数据相关资源