hdu 4568 hunter
2015-10-13 22:22
183 查看
第一次做最短路的题型,花了好久学习最短路。做题,测试时发现有bug,找了4个小时,终于找了出来。尼玛,开心死了!
先用spfa算法算出每个宝藏点之间的最短路径,然后就变成了裸的状态压缩dp了。
建议先做1074题和3182题。
ro[i][0]表示第i个宝藏点距离边界的最短距离。
状态压缩思路同1074和3182差不多。
先用spfa算法算出每个宝藏点之间的最短路径,然后就变成了裸的状态压缩dp了。
建议先做1074题和3182题。
ro[i][0]表示第i个宝藏点距离边界的最短距离。
状态压缩思路同1074和3182差不多。
#include<iostream> #include<algorithm> #include<cstdio> #include<queue> #include<cstring> using namespace std; struct node { int x,y,num; bool operator <(const node& b)const { return num>b.num; } }; struct node2 { int x,y; }a[15]; const int N=205; int vis ; //标记某个点是否被访问过 int map ;//存储地图 int soc ; //记下每个宝藏点的编号 int ro[20][20];//储存每个宝藏点间的最短路径 int t; int n,m,k; int dir[4][2]={1,0,-1,0,0,1,0,-1}; int dp[1<<16][20]; void bfs(int ii) { node fi,now,hd; memset(vis,0,sizeof(vis)); hd.x=a[ii].x; hd.y=a[ii].y; hd.num=0; priority_queue<node> q; q.push(hd); int v[20]={0}; v[ii]=1; int num=1; vis[hd.x][hd.y]=1; while(!q.empty()) { fi=q.top(); q.pop(); if((fi.x==0||fi.y==0||fi.x==n-1||fi.y==m-1)&&!v[0]) { v[0]=1; ro[ii][0]=fi.num; ro[0][ii]=fi.num+map[hd.x][hd.y]; /* cout<<ro[k][0]<<" "<<ro[0][k]<<endl;*/ num++; if(num==k+1) return; } int id=soc[fi.x][fi.y]; if(id&&!v[id]) { num++; v[id]=1; ro[ii][id]=fi.num; /* cout<<ro[ii][id]<<endl;*/ if(num==k+1) return ; } for(int i=0;i<4;i++) { int x=fi.x+dir[i][0]; int y=fi.y+dir[i][1]; if(x<0||y<0||x>n-1||y>m-1||map[x][y]==-1) continue; if(vis[x][y]) continue; vis[x][y]=1; now=fi; now.x=x; now.y=y; now.num+=map[x][y]; /* cout<<now.num<<endl;*/ q.push(now); } } } int main() { /* freopen("in.txt","r",stdin);*/ cin>>t; while(t--) { memset(ro,0x3f,sizeof(ro)); memset(dp,0x3f,sizeof(dp)); memset(soc,0,sizeof(soc)); cin>>n>>m; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { scanf("%d",&map[i][j]); } } cin>>k; for(int i=1;i<=k;i++) { scanf("%d%d",&a[i].x,&a[i].y); soc[a[i].x][a[i].y]=i; } if(!k) { cout<<0<<endl; continue; } for(int i=1;i<=k;i++) { bfs(i); } //cout<<ro[0][1]<<endl; //cout<<ro[1][0]<<endl; int end=(1<<(k+1)); ro[0][0]=0; for(int i=0;i<=k;i++) { dp[1<<i][i]=ro[0][i]; /* cout<<ro[0][i]<<endl;*/ } for(int i=1;i<end;i++) { for(int j=0;j<=k;j++) { if((i>>j)&1) { for(int kk=0;kk<=k;kk++) { if((i>>kk)&1) { /*cout<<dp[i][j]<<endl;*/ dp[i][j]=min(dp[i][j],dp[i&(~(1<<j))][kk]+ro[kk][j]); // cout<<kk<<" "<<j<<endl; // cout<<dp[i][j]<<endl; } } } } } cout<<dp[end-1][0]<<endl; } return 0; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow
- zoj3605 Find the Marble(三维dp)
- Word Break I,II, Triangle,Palindrome Partitioning 动态规划 DP