codeforces 152E bfs+状态压缩
2015-09-10 14:03
281 查看
/*题意:在一些n*m的网格中 每个格子里面都有一些不同数量的花 问现在要使得一些给定的重要位置联通 你需要破坏至少多少花来使得道路联通*/ /* 我们采用暴力的思维 把重要位置当成状态来处理 然后枚举出发的位置点 取最优结果就ok啦*/ #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<sstream> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #include<vector> using namespace std; typedef long long ll; #define inf 1<<29 #define eps 1e-10 #define maxl 210 #define mem(i,j) memset(i,j,sizeof(i)) int dp[maxl][1<<7],pre[maxl][1<<7];//状态压缩 dp表示从网格中某个格子出发访问过某几个所需要的最小花费 int n,m,k,nn,mm; int hash1[maxl]; int maz[maxl][maxl];//初始值 char g[maxl][maxl];//保存结果 bool visit[maxl][1<<7]; int dx[]= {0,0,-1,1}; int dy[]= {-1,1,0,0}; struct Node { int u,st; Node(int _u,int _st) { u=_u,st=_st; } }; queue<Node> que; bool check(int x,int y) { if(x>=0&&x<n&&y>=0&&y<m) return true; return false; } void update(int u,int st,int w,int fa) { if(dp[u][st]>w)//累计和 { dp[u][st]=w; pre[u][st]=fa; if(!visit[u][st]) { que.push(Node(u,st)); visit[u][st]=true; } } } void dfs(int u,int st) { int x=u/m,y=u%m; g[x][y]='X'; if(pre[u][st]==-1) return ; else { int v=pre[u][st]/1000,stt=pre[u][st]%1000; dfs(v,stt); if(stt-st) dfs(v,st-stt); } } void solve() { while(!que.empty()) { Node now=que.front(); que.pop(); int u=now.u,x=now.u/m,y=now.u%m,st=now.st;//取出得到对应行列 visit[u][st]=false; for(int i=0; i<4; i++) { int xx=x+dx[i],yy=dy[i]+y; if(!check(xx,yy)) continue; int v=xx*m+yy; update(v,st,dp[u][st]+maz[xx][yy],u*1000+st);//向四周扩展 } //这部分是最关键的 int t=mm-1-st; for(int i=t; i; i=(i-1)&t)//i指的就是取另外与st无交集的另外一些 { update(u,i|st,dp[u][i]+dp[u][st]-maz[x][y],u*1000+st);//注意这里减去重复的部分 因为是从st 这个点的位置出发走了俩次 所以减去 } } int ans=inf,u; for(int i=0; i<nn; i++) if(ans>dp[i][mm-1])//mm-1表示全部访问完成 看从图上的那个格子出发取的最小 { ans=dp[i][mm-1]; u=i; } dfs(u,mm-1); cout<<ans<<endl; for(int i=0; i<n; i++) { for(int j=0; j<m; j++) cout<<g[i][j]; cout<<endl; } } int main() { freopen("in.txt", "r", stdin); while(cin>>n>>m>>k) { for(int i=0; i<n; i++) for(int j=0; j<m; j++) { cin>>maz[i][j]; g[i][j]='.'; } nn=n*m; mm=1<<k; memset(hash1,0,sizeof(hash1)); memset(visit,false,sizeof(visit)); for(int i=0; i<nn; i++) for(int j=0; j<mm; j++) dp[i][j]=inf; for(int i=0,a,b; i<k; i++) { cin>>a>>b; a--,b--; int u=a*m+b; hash1[u]=1<<i; update(u,hash1[u],maz[a][b],-1); } solve(); } }
相关文章推荐
- 业界大牛级程序员给程序员的一些建议
- iOS开发:界面传值之Block传值
- ^(^=)是什么以及他的运算规则
- SessionState的配置(web.config)
- 个人或团队项目怎么起包名
- SQL常用语句
- MSTSC 自动登录
- [Android] Android开发优化之——使用软引用和弱引用
- LinkedList源码分析
- Django学习笔记1
- iOS-判断字符串中是否只含有\n
- linux安装包制作
- pdf转换成txt格式的方法与步骤
- 在arm上搭建flask运行环境
- 使用MsgPack配合Qt应用程序和node.js应用程序的数据传输
- Android style
- framework制作
- gradle安装记录
- Kaldi中的nnet3之数据类型
- SVN学习笔记9 -- SVN Eclipse 插件安装-- 新的旅程