codeforces 152E bfs+状态压缩

来源:互联网 发布:男生暗恋女生知乎 编辑:程序博客网 时间:2024/04/29 20:22
/*题意:在一些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();    }}

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 劳动法规定身体有疾病的怎么办 铁路对职工醉驾怎么办 入职体检高血糖怎么办 睾丸捏一下很疼怎么办 小孩睾丸受外力红肿该怎么办 睾丸炎症怎么办啊会不会不育呢 腰疼连着睾丸疼怎么办 为什么结石会睾丸疼怎么办 感觉自己睾丸变小了怎么办 宝宝小丁丁肿了怎么办 两岁宝宝高低肩怎么办 参军体检视力不过关怎么办 验兵视力不过关怎么办 军检了感冒了怎么办 双侧附睾头囊肿怎么办 睾丸上面长疙瘩很痒都抓烂了怎么办 睾丸小引起精子数量少怎么办 睾丸发育不完全精子存活率低怎么办 踢到睾丸很痛怎么办 兔子的睾丸烂了怎么办 梗阻性无精穿刺取得精子不好怎么办 甲状腺做完穿刺后是恶性怎么办 硬了之后睾丸痛怎么办 腋下胯间颜色深怎么办 当兵前上班有社保怎么办 别人背后害我我怎么办 左侧胸明显大于右侧胸怎么办 婴儿拉大便次数多怎么办 公鸽子不会踩蛋怎么办 生殖器套东西取不下来怎么办 婴儿成蛋蛋的皮好长怎么办 丈夫总要害自己该怎么办 脚背踢肿了怎么办很疼 踢沙袋脚背伤了怎么办 脚y子烂了怎么办 掐喉咙那会痒会咳嗽怎么办 掐到婴儿脖子了怎么办 孩子胳膊不小心烫破皮了怎么办 孩子嘴角磕破了怎么办 电话不小心拒接了怎么办 手机微信不小心碰到语言英文怎么办