王者之剑题解
Posted Forever_goodboy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了王者之剑题解相关的知识,希望对你有一定的参考价值。
2051. 王者之剑
时间限制:1 s 内存限制:256 MB
【题目描述】
这是在阿尔托利亚·潘德拉贡成为英灵前的事情,她正要去拔出石中剑成为亚瑟王,在这之前她要去收集一些宝石。
宝石排列在一个n*m的网格中,每个网格中有一块价值为v(i,j)的宝石,阿尔托利亚·潘德拉贡可以选择自己的起点。
开始时刻为0秒。以下操作,每秒按顺序执行
1.在第i秒开始的时候,阿尔托利亚·潘德拉贡在方格(x,y)上,她可以拿走(x,y)中的宝石。
2.在偶数秒,阿尔托利亚·潘德拉贡周围四格的宝石会消失
3.若阿尔托利亚·潘德拉贡第i秒开始时在方格(x,y)上,则在第i+1秒可以立即移动到(x+1,y),(x,y+1),(x-1,y)或(x,y-1)上,也可以停留在(x,y)上。
求阿尔托利亚·潘德拉贡最多可以获得多少价值的宝石
【输入格式】
第一行给出数字N,M代表行列数.N,M均小于等于100,宝石的价值不会超过10000.下面N行M列用于描述数字矩阵
【输出格式】
输出最多可以拿到多少价值宝石
【样例输入】
2 2
1 2
2 1
【样例输出】
4
solution:
这个题其实很简单,我们不用去管如何走,只要取得格子相容一定会有合法路径。
有不相容的便想到了最小割,割掉最小不相容的点,获得最大利益。
先将棋盘黑白染色,将白色的点和S连接,边权为容量;再将黑色的点和T连接,边权也是容量。
这时再将所有白色的点和周围不相容的点连接,边权为inf。S对于白点就是取,从路径来说,S-白—黑—T,因为中间部分容量为inf,所以只能割掉两边的边,割掉的就是舍弃的格子。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 #define min(a,b) ((a)<(b)?(a):(b)) 6 #define inf 1e9 7 int read() { 8 int s=0,f=1; 9 char ch=getchar(); 10 while(ch>‘9‘||ch<‘0‘) { 11 if(ch==‘-‘) { 12 f=-1; 13 } 14 ch=getchar(); 15 } 16 while(ch>=‘0‘&&ch<=‘9‘) { 17 s=(s<<1)+(s<<3)+(ch^48); 18 ch=getchar(); 19 } 20 return s*f; 21 } 22 int n,m,zong,num[105][105],S,T,val[10005],tot,r[10005],sum; 23 bool col[10005]; 24 struct oo { 25 int to,next,vv; 26 } c[200005]; 27 void add(int x,int y,int z) { 28 c[tot].to=y; 29 c[tot].vv=z; 30 c[tot].next=r[x]; 31 r[x]=tot++; 32 } 33 void readandprint() { 34 memset(r,-1,sizeof(r)); 35 n=read(); 36 m=read(); 37 int state=1; 38 S=0,T=n*m+1; 39 for(int i=1; i<=n; i++) { 40 for(int j=1; j<=m; j++) { 41 num[i][j]=++zong; 42 val[num[i][j]]=read(); 43 sum+=val[num[i][j]]; 44 } 45 } 46 T=zong+1; 47 for(int j=1; j<=m; j++) { 48 col[num[1][j]]=state; 49 state^=1; 50 } 51 for(int i=2; i<=n; i++) { 52 for(int j=1; j<=m; j++) { 53 col[num[i][j]]=col[num[i-1][j]]^1; 54 } 55 } 56 for(int i=1;i<=n;i++){ 57 for(int j=1;j<=m;j++){ 58 if(!col[num[i][j]]) { //bai 59 add(S,num[i][j],val[num[i][j]]); 60 add(num[i][j],S,0); 61 } 62 if(col[num[i][j]]) { //hei 63 add(num[i][j],T,val[num[i][j]]); 64 add(T,num[i][j],0); 65 } 66 } 67 } 68 69 for(int i=1; i<=n; i++) { 70 for(int j=1; j<=m; j++) { 71 if(!col[num[i][j]]){ 72 if(i<n) { 73 add(num[i][j],num[i+1][j],inf); 74 add(num[i+1][j],num[i][j],0); 75 } 76 if(j<m) { 77 add(num[i][j],num[i][j+1],inf); 78 add(num[i][j+1],num[i][j],0); 79 } 80 if(i>1) { 81 add(num[i][j],num[i-1][j],inf); 82 add(num[i-1][j],num[i][j],0); 83 } 84 if(j>1) { 85 add(num[i][j],num[i][j-1],inf); 86 add(num[i][j-1],num[i][j],0); 87 } 88 } 89 } 90 } 91 } 92 int queue[100005],head,tail,deep[10005]; 93 bool bfs(int s,int t) { 94 memset(deep,0,sizeof(deep)); 95 head=tail=0; 96 deep[s]=1; 97 queue[++tail]=s; 98 while(head<tail) { 99 int opt=queue[++head]; 100 for(int i=r[opt]; ~i; i=c[i].next) { 101 if(c[i].vv&&!deep[c[i].to]) { 102 deep[c[i].to]=deep[opt]+1; 103 queue[++tail]=c[i].to; 104 if(c[i].to==t) { 105 return 1; 106 } 107 } 108 } 109 } 110 return 0; 111 } 112 int dfs(int opt,int fw) { 113 if(opt==T) { 114 return fw; 115 } 116 int tmp=fw,k; 117 for(int i=r[opt]; ~i; i=c[i].next) { 118 if(tmp&&c[i].vv&&deep[c[i].to]==deep[opt]+1) { 119 k=dfs(c[i].to,min(c[i].vv,tmp)); 120 if(!k) { 121 deep[c[i].to]=0; 122 continue; 123 } 124 c[i].vv-=k; 125 c[i^1].vv+=k; 126 tmp-=k; 127 } 128 } 129 return fw-tmp; 130 } 131 int dinic(int s,int t) { 132 int ans=0; 133 while(bfs(s,t)) { 134 ans+=dfs(s,inf); 135 } 136 return ans; 137 } 138 int Main(){ 139 freopen("Excalibur.in","r",stdin); 140 freopen("Excalibur.out","w",stdout); 141 readandprint(); 142 int ans=dinic(S,T); 143 printf("%d\n",sum-ans); 144 return 0; 145 } 146 int hehe=Main(); 147 int main() { 148 ; 149 }
以上是关于王者之剑题解的主要内容,如果未能解决你的问题,请参考以下文章
JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段