srm575_div1&2_1000(网络流)
来源:互联网 发布:java前景如何 编辑:程序博客网 时间:2024/06/07 13:59
题意:给你一个N*M的矩阵,矩阵上的空位用'.'表示,非空位'X'表示。用L型的东西放进矩阵里,问最多能放多少个。
每个L型的物体可以随意旋转90度。
物体之间不能相互覆盖。
不能覆盖那些已经有X的格子。
每个L型的转角必须是黑色的格子。
一个格子是黑色,它的定义为,i+j是偶数 。
如果数据范围大一点,将所有黑色的格子标记为2,剩下的格子,如果是奇数行的标记为1,否则标记为2。从超级源点向所有标记为1的点连一条容量为1的边,从所有标记为3的点向超级汇点连一条容量为1的边,然后对于每个标记为i的点向它周围标记为i+1的点连一条容量为1的边。跑最大流。
每个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();}
- srm575_div1&2_1000(网络流)
- 网络流详解(2)
- OpenStack网络指南(2)网络组件
- 网络流学习笔记(2)
- 网络流题库2
- 网络流2
- 网络流专题2
- poj1459(网络流)
- 网络流(模板)
- 网络流(dinic)
- hdu4289Control(网络流)
- bzoj1066(网络流)
- codevs1034(网络流)
- bzoj1433(网络流)
- 网络流(EK)
- hdu5988(网络流)
- 网络编程(2)
- 网络模型(2)
- JAVA线程同步与死锁
- CentOS6上使用whois命令
- Windows中,文件所在路径查找命令
- C语言课后习题解
- ARC forbids explicit message send of release 错误
- srm575_div1&2_1000(网络流)
- 计算机视觉方面的代码
- 开始搬家
- 编程之美系列之栈和队列2—在O(1)的时间内得到队列的最大或者最小值
- android学习笔记---44_在线视频播放器,网络视频解析器,SurfaceView 控件使用方法
- [CentOS]安装rar解压工具
- dede 文章点击次数动态,可增加
- 图形画法总结
- git format-patch