王者之剑cogs

 
 

王者之剑

★★★☆   输入文件: Excalibur.in   输出文件: Excalibur.out    简单对比 时间限制: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

疯狂奇偶点!!!
偶点与四周建边
S->偶点-》四周奇点-》T
翻转源汇 S 要偶  T要奇
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<cstdlib>
#include<algorithm>
#define V 105
#define mod 1000000007
#define LL long long
using namespace std;
int n,m,sd,T,S;
int a[V][V],s[V][V],g[V][V],pre[V*V],dep[V*V],q[V*V];
struct da
{
 int to,next,dis;       
}Edge[V*V*V];
int head[V*V],tot;
inline void add(int x,int y,int zz)
{
  Edge[tot].to=y;
  Edge[tot].dis=zz;
  Edge[tot].next=head[x];
  head[x]=tot++;  
  Edge[tot].to=x;
  Edge[tot].dis=0;
  Edge[tot].next=head[y];
  head[y]=tot++;     
}
bool Bfs() {
    memset(dep, 0, sizeof(dep));
    int hd,tl;
    hd = tl = 0;
    q[++ tl] = S, dep[S] = 1;
    while(hd<tl) {
        int op = q[++hd];
        for(int i = head[op] ; i != -1 ; i = Edge[i].next) {
            if(Edge[i].dis&&(!dep[Edge[i].to])) {
                dep[Edge[i].to] = dep[op]+1;
                q[++ tl] = Edge[i].to;
                if(Edge[i].to==T) return true;
            }  
        }
    }
    return false;
}
int Dfs(int op, int fw) {
    if(op==T) return fw;           
    int tmp =fw,k;
    for(int i = head[op] ; i != -1 ; i = Edge[i].next) {
        if(Edge[i].dis&&tmp&&dep[Edge[i].to]==dep[op]+1) {
            k = Dfs(Edge[i].to, min(Edge[i].dis, tmp));
            if(!k) { 
                dep[Edge[i].to] = 0; 
                continue; 
            }
            Edge[i].dis-= k, Edge[i^1].dis+= k,tmp-= k;
        }
    }
    return fw-tmp;
}
int solve()
{
   int i,flow=0;
   while(Bfs())
   {
    flow+=Dfs(S,mod);            
   }
   return flow;
}
inline int haha()
{
    // freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
     freopen("Excalibur.in","r",stdin); freopen("Excalibur.out","w",stdout);
    memset(head,-1,sizeof(head));
    cin>>n>>m;
    //cout<<n<<" ! "<<m<<endl;
    int num=0;
    for(int i=1;i<=n;i++)
     {
         for(int j=1;j<=m;j++)
         {
           sd++;
           g[i][j]=sd;
           cin>>a[i][j];         
           s[i][j]=num;
           num^=1;   
           //cout<<g[i][j]<<" ";
         }
         num=s[i][1]^1;
        // num^=1;
        //cout<<endl;
     }
     T=g[n][m]+1;
     num=0;
     for(int i=1;i<=n;i++)
     {
         for(int j=1;j<=m;j++)
         {
             if(s[i][j])
             {
                  add(0,g[i][j],a[i][j]);          
                  if(i>1)
                  add(g[i][j],g[i-1][j],mod);
                  if(i<n)
                  add(g[i][j],g[i+1][j],mod);
                  if(j>1)
                  add(g[i][j],g[i][j-1],mod);
                  if(j<m)
                  add(g[i][j],g[i][j+1],mod);
             }
             else
             {
               add(g[i][j],T,a[i][j]);  
             }
             num+=a[i][j];
         }
     }
     printf("%d",num-solve());
    return 0;
}
int gg=haha();
int main()
{;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值