OpenJudge——0003:jubeeeeeat

衆所周知,LZF很喜歡打一個叫Jubeat的遊戲。這是個音樂遊戲,遊戲界面是4×4的方陣,會根據音樂節奏要求玩家按下一些指定方塊(如下稱combo)。LZF以爲這太簡單了,因而本身仿了個遊戲叫Jubeeeeeat,惟一不一樣之處就是界面大小,Jubeeeeeat的界面爲n×n的方陣。ios

在某一刻,界面同時出現了若干個combo。LZF終於以爲有些困難了,但畢竟LZF不是普通人,他有不少隻手。LZF的手分爲m只「肉質手」和q只「意念手」。顧名思義,「肉質手」是實際存在的手,每隻肉質手都有5根手指,每根手指能按一個combo,但每隻手的速度都不一樣,受限於此,LZF的每隻肉質手的控制範圍是一個固定大小的正方形。「意念手」即虛無之手,每隻手只有1根手指,但控制範圍爲全局。網絡

如今LZF想知道,他最多能按下多少個combo。spa

 

輸入
輸入文件名爲 jubeeeeeat.in。 
第1行輸入三個正整數n,m,q。
接下來是一個n×n的01矩陣,描述combo的位置,1爲combo。
最後m行每行三個正整數xi,yi,ai,分別表示第i只肉質手掌控區域左上方塊的行、列和邊長。(行、列從1數起)
輸出
輸出文件名爲 jubeeeeeat.out。 
輸出一個正整數,表示最多能按下的combo數。
樣例輸入
3 1 3
1 0 1
1 1 1
1 0 1
1 1 2
樣例輸出
6
提示
【數聽說明】
對於20%的數據,n=5,m=2,q=2;
對於50%的數據,1≤n≤20,1≤m, q≤50;
對於100%的數據,1≤n≤40,1≤m, q≤300,1≤xi, yi≤n,1≤xi+ai-1, yi+ai-1≤n。
 
 
 
網絡流
源點向每一隻肉質手連一條流量爲5的邊,而後每一隻肉質手向他所能管到的格子連一條流量爲1的邊, 每個格子向源點連一條流量爲1的邊,而後跑最大流
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 200100
#define inf 9999999
using namespace std;
queue<int>q;
int n,p,m,x,y,z,s,e,ans,maxn,tot=1,a[100][100];
int to[N],lev[N],cap[N],cnt[N],head[N],nextt[N];
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int add(int x,int y,int z)
{
    tot++;to[tot]=y,cap[tot]=z,nextt[tot]=head[x];head[x]=tot;
    tot++;to[tot]=x;cap[tot]=0,nextt[tot]=head[y];head[y]=tot;
}
inline bool bfs()
{
    while(!q.empty()) q.pop();
    for(int i=0;i<=n*n+m+1;i++)
    {
        lev[i]=-1;
        cnt[i]=head[i];
    }
    q.push(s),lev[s]=0;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=head[x];i;i=nextt[i])
        {
            int t=to[i];
            if(cap[i]>0&&lev[t]==-1)
            {
                lev[t]=lev[x]+1;
                q.push(t);
                if(t==e) return true;
            }
        }
    }
    return false;
}
int dinic(int x,int flow)
{
    if(x==e) return flow;
    int rest=0,delta;
    for(int &i=cnt[x];i;i=nextt[i])
    {
        int t=to[i];
        if(cap[i]>0&&lev[t]==lev[x]+1)
        {
            delta=dinic(t,min(cap[i],flow-rest));
            if(delta)
            {
                rest+=delta;
                cap[i]-=delta;
                cap[i^1]+=delta;
                if(rest==flow) break;
            }
        }
    }
    if(rest!=flow) lev[x]=-1;
    return rest;
}
int main()
{
    n=read(),m=read(),p=read();
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     {
         a[i][j]=read();
         if(a[i][j]) maxn++;
      } 
    e=n*n+m+1;
    for(int i=1;i<=m;i++)
     add(s,i,5);
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();
        for(int j=x;j<x+z;j++)
         for(int k=y;k<y+z;k++)
          if(a[j][k])
           add(i,m+(j-1)*n+k,1);
    }
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      if(a[i][j])
       add(m+(i-1)*n+j,e,1);
    while(bfs()) ans+=dinic(s,inf);
    ans=min(ans+p,maxn);
    printf("%d",ans);
    return  0;
}
相關文章
相關標籤/搜索