cogs 2051. 王者之剑

【题目描述】

这是在阿尔托利亚·潘德拉贡成为英灵前的事情,她正要去拔出石中剑成为亚瑟王,在这之前她要去收集一些宝石。

宝石排列在一个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;
 11 };
 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 }
code

 

posted @ 2017-07-29 19:41  A_LEAF  阅读(196)  评论(0编辑  收藏  举报