王者之剑

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

宝石排列在一个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

【题解】
论黑白点染色是怎样一个常用套路……因为每个点和它周围一圈的四个点一定不能同时拿到,而且只有偶数时刻可以取数,所以把不相容的点之间建一条权值极大的边。每个黑点和源点、白点和汇点之间的边权值为这个点的价值。对于白点来说汇点的意义是选、源点是不选,对于黑点正相反,这就是翻转源汇的思想。最小割中割掉的边是被舍弃的边,用刚开始矩阵的总权值减去割的权值即可。注意即使建极大值的边也是正向极大反向为0,否则可能会出现很多不可知的错误。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int sj=105;
int n,m,vl[sj][sj],h[sj*sj],e,s,t,sx[sj][sj],jg,dep[sj*sj],ma;
bool hb[sj][sj];
struct B
{
     int ne,v,w;
}b[sj*sj*10];
void add(int x,int y,int z)
{
     b[e].v=y;
     b[e].w=z;
     b[e].ne=h[x];
     h[x]=e++;
}
int bj(int x,int y)
{
    return x<y?x:y;
}
void init()
{
     scanf("%d%d",&n,&m);
     memset(h,-1,sizeof(h));
     s=0;
     t=n*m+1;
     ma=1000010;
     for(int i=1;i<=n;i++)
       for(int j=1;j<=m;j++)
       { 
         scanf("%d",&vl[i][j]);
         if((i&1)==(j&1)) hb[i][j]=1;
         jg+=vl[i][j];
         sx[i][j]=m*(i-1)+j;
       }
     for(int i=1;i<=n;i++)
       for(int j=1;j<=m;j++)
       {
         if(hb[i][j]) 
         {
           add(s,sx[i][j],vl[i][j]),add(sx[i][j],s,0);
           if(i-1)
             add(sx[i][j],sx[i-1][j],ma),add(sx[i-1][j],sx[i][j],0);
           if(j-1)
             add(sx[i][j],sx[i][j-1],ma),add(sx[i][j-1],sx[i][j],0);
           if(i+1<=n)
             add(sx[i][j],sx[i+1][j],ma),add(sx[i+1][j],sx[i][j],0);
           if(j+1<=m)
             add(sx[i][j],sx[i][j+1],ma),add(sx[i][j+1],sx[i][j],0);     
         }
         if(!hb[i][j])
           add(sx[i][j],t,vl[i][j]),add(t,sx[i][j],0);
       }
}
queue<int> q;
bool bfs(int x)
{
    memset(dep,0,sizeof(dep));
    dep[x]=1;
    while(!q.empty()) q.pop();
    q.push(x);
    while(!q.empty())
    {
       x=q.front();
       q.pop();
       for(int i=h[x];i!=-1;i=b[i].ne)
         if(b[i].w&&!dep[b[i].v])
         {
            dep[b[i].v]=dep[x]+1;
            if(b[i].v==t) return 1;
            q.push(b[i].v);
         }
    }
    return 0;
}
int dfs(int x,int f)
{
    int ans=0;
    if(x==t) return f;
    for(int i=h[x],d;i!=-1;i=b[i].ne)
      if(b[i].w&&dep[b[i].v]>dep[x])
      {
         d=dfs(b[i].v,bj(b[i].w,f));
         f-=d;
         ans+=d;
         b[i].w-=d;
         b[i^1].w+=d;
      }
    if(!ans) dep[x]=-1;
    return ans;
}
int main()
{
    //freopen("t.txt","r",stdin);
    freopen("Excalibur.in","r",stdin);
    freopen("Excalibur.out","w",stdout);
    init();
    while(bfs(s)) jg-=dfs(s,ma*100);
    printf("%d",jg);
    //while(1);
    return 0;
}
Excalibur

 

 
posted @ 2017-07-31 06:20  moyiii  阅读(182)  评论(0编辑  收藏  举报