srm575_div1&2_1000(网络流)

来源:互联网 发布:java前景如何 编辑:程序博客网 时间:2024/06/07 13:59
题意:给你一个N*M的矩阵,矩阵上的空位用'.'表示,非空位'X'表示。用L型的东西放进矩阵里,问最多能放多少个。
每个L型的物体可以随意旋转90度。
  物体之间不能相互覆盖。
不能覆盖那些已经有X的格子。
每个L型的转角必须是黑色的格子。
一个格子是黑色,它的定义为,i+j是偶数 。


如果数据范围小的话,用当前列的去更新下一列的,当前列可能对应着不同的方格占据方案,那么利用位压缩去对应各种不同的占据情况,那么这就是一个DP。

const int N=55;string tile[][2] = {    {".X",    "XB"},    {"X.",    "BX"},    {"BX",    "X."},    {"XB",    ".X"}};class TheTilesDivTwo {public:int find(vector <string>);int dp[20][N];bool cell[20][N],board[20][N];int row,column;bool check(char chr,int i,int j){    if(chr=='.') return 1;    if(cell[i][j]+board[i][j]!=0) return 0;    if(chr=='B')    {        if((i+j)%2==0) return 1;        else return 0;    }    return 1;}void dfs(int state,int col,int r,int cnt){    if(r==row-1)    {        int ns=0;        for(int i=0;i<row;i++) if(cell[i][col+1])        {            ns|=(1<<i);        }        dp[ns][col+1]=max(dp[ns][col+1],dp[state][col]+cnt);        return ;    }    dfs(state,col,r+1,cnt);    for(int t=0;t<4;t++)    {        bool ok=1;        for(int i=0;i<2;i++)            {                for(int j=0;j<2;j++)                {                    if(check(tile[t][i][j],r+i,col+j)==0) ok=0;                }            }            if(ok==0) continue;            for(int i=0;i<2;i++)            {                for(int j=0;j<2;j++)                {                    if(tile[t][i][j]!='.') cell[r+i][col+j]=1;                }            }            dfs(state,col,r+1,cnt+1);            for(int i=0;i<2;i++)            {                for(int j=0;j<2;j++)                {                    if(tile[t][i][j]!='.') cell[r+i][col+j]=0;                }            }    }}};int TheTilesDivTwo::find(vector <string> board_) {row=(int)board_.size();column=(int)board_[0].length();memset(dp,-1,sizeof(dp));memset(board,0,sizeof(board));memset(cell,0,sizeof(cell));for(int i=0;i<row;i++){    for(int j=0;j<column;j++) if(board_[i][j]=='X')    {        board[i][j]=1;    }}dp[0][0]=0;for(int j=0;j<column;j++){    for(int i=0;i<(1<<row);i++) if(dp[i][j]!=-1)    {        memset(cell,0,sizeof(cell));        for(int k=0;k<row;k++) if(i&(1<<k)) cell[k][j]=1;        dfs(i,j,0,0);    }}int ans=0;for(int i=0;i<(1<<row);i++) ans=max(ans,dp[i][column-1]);return ans;}

如果数据范围大一点,将所有黑色的格子标记为2,剩下的格子,如果是奇数行的标记为1,否则标记为2。从超级源点向所有标记为1的点连一条容量为1的边,从所有标记为3的点向超级汇点连一条容量为1的边,然后对于每个标记为i的点向它周围标记为i+1的点连一条容量为1的边。跑最大流。

#include <iostream>#include <cstdio>#include <vector>#include <string>#include <cstring>using namespace std;const int N=100005;const int M=400005;#define INF 0x3f3f3f3fstruct Edge{    int u,v,flow,cap,pre;    Edge(){}    Edge(int u,int v,int cap,int pre) :        u(u),v(v),cap(cap),pre(pre) {flow=0;}}edge[M];int head[N],tot;void addEdge(int u,int v,int cap){    edge[tot]=Edge(u,v,cap,head[u]);    head[u]=tot++;    edge[tot]=Edge(v,u,0,head[v]);    head[v]=tot++;}void init() //添加边之前要先初始化。{    tot=0;    memset(head,-1,sizeof(head));}struct MaxFlow{    int st,ed,n,mx_flow;//表示起点,终点,有多少个点,所求的最大流是多少。    int dis[N],gap[N],cur[N],aug[N],path[N];    //dis表示每个点的距离标记,gap表示距离为i的点有多少个,cur用于当前孤优化,    //aug记录找到的增广路流量,path记录找到的增广路的路径。    void init()    {        for(int i=0;i<=n;i++)        {            aug[i]=gap[i]=dis[i]=0;            cur[i]=head[i];        }        aug[st]=INF;    gap[0]=n;        mx_flow=0;    }    int augment(int &point)//修改找到的增广路上的边的容量,当前点修改为起点。    {        for(int i=ed;i!=st;i=edge[path[i]].u)        {            int pair=path[i]^1;            edge[ path[i] ].flow+=aug[ed];            edge[ pair ].flow-=aug[ed];        }        point=st;        return aug[ed];    }    int solve()    {        init();        int u=st;        while(dis[st]<n)        {            if(u==ed) mx_flow+=augment(u);            bool flag=1;            for(int i=head[u];i!=-1;i=edge[i].pre)            {                int v=edge[i].v;                if(edge[i].cap-edge[i].flow>0&&dis[u]==dis[v]+1)                {                    path[v]=i;  cur[u]=i;                    aug[v]=min(aug[u],edge[i].cap-edge[i].flow);                    u=v;                    flag=0; break;                }            }            if(flag)            {                if(--gap[dis[u]]==0) return mx_flow;                dis[u]=N;                for(int i=head[u];i!=-1;i=edge[i].pre)                {                    int v=edge[i].v;                    if(edge[i].cap-edge[i].flow>0) dis[u]=min(dis[u],dis[v]+1);                }                gap[dis[u]]++;                cur[u]=head[u];                if(u!=st) u=edge[path[u]].u;            }        }        return mx_flow;    }}sap;const int dx[]= {0,0,1,-1};const int dy[]= {1,-1,0,0};class TheTilesDivOne{public:    int find(vector <string>);    int lab[55][55];    int in[10000],out[10000];    int n,m;    int calu(int x,int y)    {        return x*m+y;    }};int TheTilesDivOne::find(vector <string> board_){    memset(lab,-1,sizeof(lab));    memset(in,-1,sizeof(in));    memset(out,-1,sizeof(out));    n=(int)board_.size();    m=(int)board_[0].length();    tot=0;  memset(head,-1,sizeof(head));    int cnt=1;    for(int i=0; i<n; i++)    {        for(int j=0; j<m; j++) if(board_[i][j]=='.')            {                in[calu(i,j)]=cnt++;                out[calu(i,j)]=cnt++;                addEdge(in[calu(i,j)],out[calu(i,j)],1);                if((i+j)%2==0) lab[i][j]=2;                else                {                    if(i%2) lab[i][j]=1;                    else lab[i][j]=3;                }            }    }    int st=0,ed=cnt;    for(int i=0; i<n; i++)    {        for(int j=0; j<m; j++) if(board_[i][j]=='.')            {                if(lab[i][j]==1)                {                    addEdge(st,in[calu(i,j)],1);                }                if(lab[i][j]==3)                {                    addEdge(out[calu(i,j)],ed,1);                }                for(int k=0; k<4; k++)                {                    int x=i+dx[k],y=j+dy[k];                    if(x>=0&&x<n&&y>=0&&y<m&&board_[x][y]=='.')                    {                        if(lab[i][j]+1==lab[x][y])                        {                            addEdge(out[calu(i,j)],in[calu(x,y)],1);                        }                    }                }            }    }    sap.st=st;  sap.ed=ed;  sap.n=cnt+1;    return sap.solve();}



原创粉丝点击