您的位置:首页 > 其它

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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: