[补档]王者之剑
王者之剑
题目
这是在阿尔托利亚·潘德拉贡成为英灵前的事情,她正要去拔出石中剑成为亚瑟王,在这之前她要去收集一些宝石。宝石排列在一个n×m的网格中,每个网格中有一块价值为v(i,j)的宝石,阿尔托利亚·潘德拉贡可以选择自己的起点。开始时刻为0秒。以下操作,每秒按顺序执行
- 在第i秒开始的时候,阿尔托利亚·潘德拉贡在方格(x,y)上,她可以拿走(x,y)中的宝石。
- 在偶数秒,阿尔托利亚·潘德拉贡周围四格的宝石会消失
- 若阿尔托利亚·潘德拉贡第i秒开始时在方格(x,y)上,则在第i+1秒可以立即移动到(x+1,y),(x,y+1),(x-1,y)或(x,y-1)上,也可以停留在(x,y)上。
求阿尔托利亚·潘德拉贡最多可以获得多少价值的宝石INPUT
第一行给出数字N,M代表行列数.N,M均小于等于100,宝石的价值不会超过10000.下面N行M列用于描述数字矩阵OUTPUT
输出最多可以拿到多少价值宝石SAMPLE
INPUT
2 21 22 1OUTPUT
4
解题报告
算是基础的最小割问题。
首先,我们取值时一定是在偶数时刻,取走一个格子的值,就不能取相邻格子的值,也就是相邻格子之间的值是不相容的。
我们想,只要取得格子相容,是一定有合法路径的,有不容的点就转化到最小割上,用总值减去割掉最小的值,就是最优解。
那么我们可以黑白染色,源点与白点相连,黑点与汇点连边,不相容的点之间连边,容量INF,跑最小割即可
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 using namespace std; 6 inline int read(){ 7 int sum(0); 8 char ch(getchar()); 9 for(;ch<'0'||ch>'9';ch=getchar()); 10 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 11 return sum; 12 } 13 struct edge{ 14 int e,n,w; 15 }a[2000001]; 16 int pre[100001],tot; 17 inline void insert(int s,int e,int w){ 18 a[tot].e=e; 19 a[tot].w=w; 20 a[tot].n=pre[s]; 21 pre[s]=tot++; 22 } 23 int n,m; 24 int w[105][105],col[105][105]; 25 inline void paint(){ 26 int now(1); 27 for(int i=1;i<=n;i++){ 28 now^=1; 29 for(int j=1;j<=m;j++){ 30 if(j&1) 31 col[i][j]=now; 32 else 33 col[i][j]=now^1; 34 } 35 } 36 } 37 int S(0),T; 38 int ans(0),inf(0x7fffffff),sum(0); 39 inline void build(){ 40 for(int i=1;i<=n;i++) 41 for(int j=1;j<=m;j++){ 42 if(col[i][j]) 43 insert(S,(i-1)*m+j,w[i][j]),insert((i-1)*m+j,S,0); 44 else 45 insert((i-1)*m+j,T,w[i][j]),insert(T,(i-1)*m+j,0); 46 } 47 for(int i=1;i<=n;i++) 48 for(int j=1;j<=m;j++){ 49 if(col[i][j]){ 50 if(i!=1) 51 insert((i-2)*m+j,(i-1)*m+j,0),insert((i-1)*m+j,(i-2)*m+j,inf); 52 if(i!=n) 53 insert(i*m+j,(i-1)*m+j,0),insert((i-1)*m+j,i*m+j,inf); 54 if(j!=1) 55 insert((i-1)*m+j-1,(i-1)*m+j,0),insert((i-1)*m+j,(i-1)*m+j-1,inf); 56 if(j!=m) 57 insert((i-1)*m+j+1,(i-1)*m+j,0),insert((i-1)*m+j,(i-1)*m+j+1,inf); 58 } 59 } 60 } 61 int dis[10010]; 62 inline bool bfs(int s,int t){ 63 memset(dis,0,sizeof(dis)); 64 dis[s]=1; 65 queue<int>q; 66 q.push(s); 67 while(!q.empty()){ 68 int k(q.front()); 69 q.pop(); 70 for(int i=pre[k];i!=-1;i=a[i].n){ 71 int e(a[i].e); 72 if(!dis[e]&&a[i].w){ 73 dis[e]=dis[k]+1; 74 q.push(e); 75 if(e==t) 76 return true; 77 } 78 } 79 } 80 return false; 81 } 82 inline int my_min(int a,int b){ 83 return a<b?a:b; 84 } 85 inline int dfs(int now,int flow){ 86 if(now==T) 87 return flow; 88 int tmp(flow),f; 89 for(int i=pre[now];i!=-1;i=a[i].n){ 90 int e(a[i].e); 91 if(dis[e]==dis[now]+1&&tmp&&a[i].w){ 92 f=dfs(e,my_min(tmp,a[i].w)); 93 if(!f){ 94 dis[e]=0; 95 continue; 96 } 97 a[i].w-=f; 98 a[i^1].w+=f; 99 tmp-=f; 100 } 101 } 102 return flow-tmp; 103 } 104 inline int gg(){ 105 freopen("Excalibur.in","r",stdin); 106 freopen("Excalibur.out","w",stdout); 107 memset(pre,-1,sizeof(pre)); 108 n=read(),m=read(); 109 T=n*m+1; 110 for(int i=1;i<=n;i++) 111 for(int j=1;j<=m;j++) 112 w[i][j]=read(),sum+=w[i][j]; 113 paint(); 114 build(); 115 while(bfs(S,T)) 116 ans+=dfs(S,inf); 117 printf("%d",sum-ans); 118 return 0; 119 } 120 int K(gg()); 121 int main(){;}