cogs 2051. 王者之劍
阿新 • • 發佈:2017-07-29
一個 最大 include cout 數字 sed cal 價值 val
【題目描述】
這是在阿爾托利亞·潘德拉貢成為英靈前的事情,她正要去拔出石中劍成為亞瑟王,在這之前她要去收集一些寶石。
寶石排列在一個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:
明確兩條性質:
1.一個寶石只能在偶數時刻被吃掉
2.最終的結果與起始位置無關
那麽我們可以將矩陣像棋盤上一樣黑白染色
由於如果一個點被吃,那麽它周圍的點一定不能被吃
所以將黑點與S(起點)連 v=1的邊 將白點與T(終點)連 v=1的邊 將黑點周圍的4個(或不到4個)白點連 v=INF的邊
最後用最大流求最小割即可
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define mem(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 const int INF=(1<<31)-1; 7 inline int minn(int a,int b){return a<b?a:b;} 8 struct son 9 { 10 int v,next,w,u;code11 }; 12 son a1[500001]; 13 int first[500001],e; 14 15 void addbian(int u,int v,int w) 16 { 17 a1[e].u=u; 18 a1[e].v=v; 19 a1[e].w=w; 20 a1[e].next=first[u]; 21 first[u]=e++; 22 } 23 24 int dui[10000001],he,en; 25 inline void clear(){he=1;en=0;} 26 inline void push(int x){dui[++en]=x;} 27 inline int top(){return dui[he];} 28 inline void pop(){++he;} 29 inline bool empty(){return en>=he?0:1;} 30 31 int n,m,u,o,S,T,sum; 32 int ji[101][101]; 33 int hh[101][101]; 34 35 int dep[20001]; 36 int bfs() 37 { 38 mem(dep,0);clear(); 39 dep[S]=1;push(S); 40 while(!empty()) 41 { 42 int now=top();pop(); 43 //printf("now=%d\n",now); 44 for(int i=first[now];i!=-1;i=a1[i].next) 45 { 46 int temp=a1[i].v; 47 //printf("temp=%d\n",temp); 48 if(!a1[i].w||dep[temp])continue; 49 dep[temp]=dep[now]+1; 50 push(temp); 51 if(temp==T)return 1; 52 } 53 } 54 return 0; 55 } 56 57 int dfs(int x,int val) 58 { 59 //printf("x=%d\n",x); 60 if(x==T)return val; 61 int val2=val,k; 62 for(int i=first[x];i!=-1;i=a1[i].next) 63 { 64 int temp=a1[i].v; 65 //printf("temp=%d\n",temp); 66 if(dep[temp]!=dep[x]+1||!a1[i].w||!val2)continue; 67 k=dfs(temp,minn(val2,a1[i].w)); 68 if(!k){dep[temp]=0;continue;} 69 a1[i].w-=k;a1[i^1].w+=k;val2-=k; 70 } 71 return val-val2; 72 } 73 74 int Dinic() 75 { 76 int ans=0; 77 while(bfs()) 78 ans+=dfs(S,INF); 79 return ans; 80 } 81 82 void out11() 83 { 84 printf("\n"); 85 /*for(int i=1;i<=n;++i) 86 { 87 for(int j=1;j<=m;++j) 88 printf("%d ",ji[i][j]); 89 printf("\n"); 90 }*/ 91 for(int i=S;i<=T;++i) 92 { 93 printf("i=%d\n",i); 94 for(int j=first[i];j!=-1;j=a1[j].next) 95 printf("%d ",a1[j].v); 96 printf("\n"); 97 } 98 printf("\n"); 99 } 100 101 int main(){ 102 //freopen("1.txt","r",stdin); 103 freopen("Excalibur.in","r",stdin); 104 freopen("Excalibur.out","w",stdout); 105 mem(first,-1); 106 scanf("%d%d",&n,&m); 107 S=0;T=n*m+1; 108 for(int i=1;i<=m;++i) 109 ji[1][i]=i&1; 110 for(int i=2;i<=n;++i) 111 { 112 ji[i][1]=ji[i-1][2]; 113 for(int j=2;j<=m;++j) 114 ji[i][j]=ji[i-1][j-1]; 115 } 116 117 for(int i=1;i<=n;++i) 118 for(int j=1;j<=m;++j) 119 hh[i][j]=(i-1)*m+j; 120 121 //out11(); 122 123 for(int i=1;i<=n;++i) 124 for(int j=1;j<=n;++j) 125 { 126 scanf("%d",&u); 127 sum+=u; 128 if(ji[i][j]) 129 { 130 addbian(S,hh[i][j],u); 131 addbian(hh[i][j],S,0); 132 } 133 else 134 { 135 addbian(hh[i][j],T,u); 136 addbian(T,hh[i][j],0); 137 } 138 } 139 140 //out11(); 141 142 for(int i=1;i<=n;++i) 143 for(int j=1;j<=m;++j) 144 if(ji[i][j]) 145 { 146 if(i>1) 147 { 148 addbian(hh[i][j],hh[i-1][j],INF); 149 addbian(hh[i-1][j],hh[i][j],0); 150 } 151 if(i<n) 152 { 153 addbian(hh[i][j],hh[i+1][j],INF); 154 addbian(hh[i+1][j],hh[i][j],0); 155 } 156 if(j>1) 157 { 158 addbian(hh[i][j],hh[i][j-1],INF); 159 addbian(hh[i][j-1],hh[i][j],0); 160 } 161 if(j<m) 162 { 163 addbian(hh[i][j],hh[i][j+1],INF); 164 addbian(hh[i][j+1],hh[i][j],0); 165 } 166 } 167 168 //out11(); 169 170 //cout<<0; 171 printf("%d",sum-Dinic()); 172 //while(1); 173 return 0; 174 }
cogs 2051. 王者之劍