jubeeeeeat(网络流)

jubeeeeeat

总时间限制: 
1000ms
 
内存限制: 
256000kB

描述

众所周知,LZF很喜欢打一个叫Jubeat的游戏。这是个音乐游戏,游戏界面是4×4的方阵,会根据音乐节奏要求玩家按下一些指定方块(以下称combo)。LZF觉得这太简单了,于是自己仿了个游戏叫Jubeeeeeat,唯一不同之处就是界面大小,Jubeeeeeat的界面为n×n的方阵。

在某一刻,界面同时出现了若干个combo。LZF终于觉得有些困难了,但毕竟LZF不是普通人,他有很多只手。LZF的手分为m只“肉质手”和q只“意念手”。顾名思义,“肉质手”是实际存在的手,每只肉质手都有5根手指,每根手指能按一个combo,但每只手的速度都不同,受限于此,LZF的每只肉质手的控制范围是一个固定大小的正方形。“意念手”即虚无之手,每只手只有1根手指,但控制范围为全局。

现在LZF想知道,他最多能按下多少个combo。

输入

输入文件名为 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。

code

输出没有换行符。。。

 1 #include<cstdio>
 2 #include<algorithm>
 3 
 4 using namespace std;
 5 
 6 const int INF = 1e9;
 7 const int N = 100100;
 8 
 9 struct Edge{
10     int to,nxt,c;
11 }e[N];
12 int q[500100],head[N],cur[N],dis[N],mp[50][50];
13 int S,T,L,R,tot=1,tn;
14 
15 inline char nc() {
16     static char buf[100000],*p1 = buf,*p2 = buf;
17     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
18 }
19 inline int read() {
20     int x = 0,f = 1;char ch = nc();
21     for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f = -1;
22     for (; ch>='0'&&ch<='9'; ch = nc()) x = x * 10 + ch - '0';
23     return x * f;
24 }
25 inline void add_edge(int u,int v,int w) {
26     e[++tot].to = v,e[tot].c = w,e[tot].nxt = head[u],head[u] = tot;
27     e[++tot].to = u,e[tot].c = 0,e[tot].nxt = head[v],head[v] = tot;
28 }
29 inline bool bfs() {
30     for (int i=1; i<=tn; ++i) {
31         cur[i] = head[i];dis[i] = -1;
32     }
33     L = 1;R = 0;
34     q[++R] = S;dis[S] = 0;
35     while (L <= R) {
36         int u = q[L++];
37         for (int i=head[u]; i; i=e[i].nxt) {
38             int v = e[i].to,c = e[i].c;
39             if (dis[v]==-1 && c > 0) {
40                 dis[v] = dis[u] + 1;
41                 q[++R] = v;
42                 if (v == T) return true;
43             }
44         }
45     }
46     return false;
47 }
48 int dfs(int u,int flow) {
49     if (u==T) return flow;
50     int used = 0;
51     for (int &i=cur[u]; i; i=e[i].nxt) {
52         int v = e[i].to,c = e[i].c;
53         if (dis[v]==dis[u]+1 && c>0) {
54             int tmp = dfs(v,min(c,flow-used));
55             if (tmp > 0) {
56                 e[i].c -= tmp;e[i^1].c += tmp;
57                 used += tmp;
58                 if (used==flow) break;
59             }
60         }
61     }
62     if (used != flow) dis[u] = -1;
63     return used;
64 }
65 inline int dinic() {
66     int ans = 0;
67     while (bfs()) ans += dfs(S,INF);
68     return ans;
69 }
70 int main() {
71     int n = read(),m = read(),h = read(),cnt = 0;
72     tn = n*n+m+2;
73     S = tn-1,T = tn;
74     for (int i=1; i<=n; ++i) 
75         for (int j=1; j<=n; ++j)
76             mp[i][j] = read();
77     for (int i=1; i<=m; ++i) add_edge(S,i,5);
78     for (int a,b,c,k=1; k<=m; ++k) {
79         a = read(),b = read(),c = read();
80         for (int i=a; i<(a+c); ++i) 
81             for (int j=b; j<(b+c); ++j) 
82                 if (mp[i][j]) add_edge(k,(i-1)*n+j+m,1);
83     }
84     for (int i=1; i<=n; ++i) 
85         for (int j=1; j<=n; ++j)
86             if (mp[i][j]) cnt++,add_edge((i-1)*n+j+m,T,1);
87     int tmp = dinic();
88     printf("%d",min(tmp+h,cnt));    
89     return 0;
90 }
原文地址:https://www.cnblogs.com/mjtcn/p/8093341.html