Codeforces 677D Vanya and Treasure【dp+极限思维剪枝】
来源:互联网 发布:淘宝男款外套 编辑:程序博客网 时间:2024/05/02 16:28
Vanya is in the palace that can be represented as a grid n × m. Each room contains a single chest, an the room located in thei-th row and j-th columns contains the chest of typeaij. Each chest of typex ≤ p - 1 contains a key that can open any chest of typex + 1, and all chests of type 1 are not locked. There is exactly one chest of type p and it contains a treasure.
Vanya starts in cell (1, 1) (top left corner). What is the minimum total distance Vanya has to walk in order to get the treasure? Consider the distance between cell(r1, c1) (the cell in the rowr1 and columnc1) and (r2, c2) is equal to|r1 - r2| + |c1 - c2|.
The first line of the input contains three integers n,m and p (1 ≤ n, m ≤ 300, 1 ≤ p ≤ n·m) — the number of rows and columns in the table representing the palace and the number of different types of the chests, respectively.
Each of the following n lines contains m integers aij (1 ≤ aij ≤ p) — the types of the chests in corresponding rooms. It's guaranteed that for each x from 1 to p there is at least one chest of this type (that is, there exists a pair ofr and c, such thatarc = x). Also, it's guaranteed that there is exactly one chest of typep.
Print one integer — the minimum possible total distance Vanya has to walk in order to get the treasure from the chest of typep.
3 4 32 1 1 11 1 1 12 1 1 3
5
3 3 91 3 58 9 74 6 2
22
3 4 121 2 3 48 7 6 59 10 11 12
11
题目大意:
一个N*M的地图上,布满了宝箱,任务就是得到编号为P的宝箱中的物品,对应我们打开了aij号宝箱,那么我们接下来就可以开aij+1号宝箱了。
所有编号为1的宝箱都是开着的,不需要钥匙。
我们最开始在左上角,问最少需要走多长的路径,就能完成任务。
思路:
1、考虑dp,设定dp【i】【j】表示开了(i,j)位子上的宝箱最少需要的路径长度。
2、那么不难推出其状态转移方程:
dp【i】【j】=min(dp【i】【j】,dp【ii】【jj】+abs(i-ii)+abs(j-jj));【此时保证a(ii,jj)+1==a(i,j)】;
但是直接暴力肯定是不行的,那么我们需要一些优化和极思维:
①我们用vector来存每个aij值都落在哪些位子上。
②考虑到P越大,对于每两个相邻编号的宝箱量,其乘积越大,需要枚举量就越大。那么当P越小的时候,假设N==300,M==300,P==3,分布1的个数为30000.分布2的个数为30000.分布3的个数也是30000的情况下,需要枚举的量是很大的。
③那么我们考虑极限思想,对于一条路径来说,肯定对于一个点(i,j)来讲,我们是很希望由dp【ii】【jj】小的来转移,那么我们不妨大胆设想,在枚举点(ii,jj)之前,将vector按照dp值从小到大排序一下,然后枚举一个量,作为最大枚举量。我一开始设定的5000.慢慢减小,到了3000就Ac了.接下来继续枚举,直到1000还是Ac的.
那么我们既然能够通过这种极限思想来剪枝Ac掉,也是很不错的做法。
Ac代码:
#include<stdio.h>#include<string.h>#include<vector>#include<iostream>#include<algorithm>using namespace std;struct node{ int dis,pos;}b[3050000],now;int a[305][305];int dp[305][305];int cmp(node a,node b){ return a.dis<b.dis;}vector<node >mp[308*308];int main(){ int n,m,p; while(~scanf("%d%d%d",&n,&m,&p)) { for(int i=1;i<=p;i++)mp[i].clear(); for(int i=0;i<n;i++)for(int j=0;j<m;j++)dp[i][j]=0x3f3f3f3f; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { scanf("%d",&a[i][j]); if(a[i][j]==1) { dp[i][j]=i+j; now.dis=dp[i][j]; } now.pos=i*m+j+1; mp[a[i][j]].push_back(now); } } sort(mp[1].begin(),mp[1].end(),cmp); for(int i=2;i<=p;i++) { int size1=mp[i].size(); int size2=mp[i-1].size(); for(int j=0;j<size1;j++) { int x=mp[i][j].pos/m,y=mp[i][j].pos%m-1; if(y<0)y=m-1,x--; for(int k=0;k<size2&&k<1000;k++) { int xx=mp[i-1][k].pos/m,yy=mp[i-1][k].pos%m-1; if(yy<0)yy=m-1,xx--; dp[x][y]=min(dp[x][y],dp[xx][yy]+abs(x-xx)+abs(y-yy)); } mp[i][j].dis=dp[x][y]; } sort(mp[i].begin(),mp[i].end(),cmp); } int output=0x3f3f3f3f; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(a[i][j]==p) output=min(dp[i][j],output); } } printf("%d\n",output); }}
- Codeforces 677D Vanya and Treasure【dp+极限思维剪枝】
- Codeforces 677D Vanya and Treasure(DP+分治) category:
- Codeforces 677D Vanya and Treasure BFS+DP (分段)
- codeforces 677 D. Vanya and Treasure
- 【12.78%】【codeforces 677D】Vanya and Treasure
- codeforces round 355 div2 D Vanya and Treasure Dp 二维线段树
- codeforce 677D. Vanya and Treasure bfs
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure
- Codeforces Round #355 (Div. 2)D. Vanya and Treasure
- [CodeForces 677D] Vanya and Treasure (二维树状数组+静态前缀最小值)
- Codeforces 677C Vanya and Label【思维】
- Codeforces 552D Vanya and Triangles【暴力枚举+思维】
- codeforces_677D. Vanya and Treasure(BFS+DP)
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure【分治+BFS】
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure (两种方法结合)
- CodeForces 552C-Vanya and Scales【思维】
- codeforces 552C Vanya and Scales 【思维】
- Codeforces 677C Vanya and Label【思维】
- NYOJ 75 日期计算
- 8 Basic Webpack Configuration&Server
- 剑指offer--调整数组顺序使奇数位于偶数前面
- Go并发编程实践
- Codeforces 677D Vanya and Treasure【dp+极限思维剪枝】
- 嵌入式设计的安全性考虑事项-ARM
- [BZOJ1828][Usaco2010 Mar]balloc 农场分配(贪心+线段树)
- GreenOpenPaint的实现(一)基本框架
- 1033. To Fill or Not to Fill (25)
- leetcode 202. Happy Number
- 1001. 害死人不偿命的(3n+1)猜想 (15)
- GreenOpenPaint的实现(六)图片的保存和打开
- c++自制小游戏(4th)结构化语言与时间空间复杂度的优化