生活随笔
收集整理的這篇文章主要介紹了
[AGC031E] Snuke the Phantom Thief(网络流)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
考慮枚舉偷的珠寶的個數k,且假設它們按照坐標大小排好了序(x坐標排一次,y坐標排一次)。
那么可以將條件轉化一下,
在珠寶按x坐標排好序時,
x坐標大于等于aia_iai?的最多取bib_ibi?個可以轉化為取的前k?bik-b_ik?bi?個珠寶的x坐標要小于aia_iai?。
同理,x坐標小于等于aia_iai?的最多可以取bib_ibi?個可以轉化為取的后k?bik-b_ik?bi?個珠寶的x坐標要大于aia_iai?。
y坐標同理。
那么這樣的話,就可以計算出取的每個珠寶的x,y坐標取值范圍。
接下來有兩種處理方法。
法一:
法二:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std
;
typedef long long ll
;
const int N
=400;
const int M
=15000;
const int inf
=2147483647;
struct Edge{int u
,v
,f
,nxt
;ll w
;
}edge
[M
<<1];
int head
[N
],cnt
,s
,t
,inque
[N
],pre
[N
];ll dis
[N
];
queue
<int> que
;
int n
,m
;ll ans
;
struct Jewelry{int x
,y
;ll val
;
}p
[85];
struct Quiery{char ch
;int a
,b
;
}q
[325];
void add(int u
,int v
,int f
,ll w
){edge
[cnt
].u
=u
;edge
[cnt
].v
=v
;edge
[cnt
].w
=w
;edge
[cnt
].f
=f
;edge
[cnt
].nxt
=head
[u
];head
[u
]=cnt
++;edge
[cnt
].u
=v
;edge
[cnt
].v
=u
;edge
[cnt
].w
=-w
;edge
[cnt
].f
=0;edge
[cnt
].nxt
=head
[v
];head
[v
]=cnt
++;
}
bool spfa(){memset(dis
,-63,sizeof(dis
));memset(inque
,0,sizeof(inque
));memset(pre
,-1,sizeof(pre
));dis
[s
]=0;que
.push(s
);inque
[s
]=1;while(!que
.empty()){int u
=que
.front();que
.pop();inque
[u
]=0;for(int i
=head
[u
];i
!=-1;i
=edge
[i
].nxt
){int v
=edge
[i
].v
;if(edge
[i
].f
>0&&dis
[v
]<dis
[u
]+edge
[i
].w
){dis
[v
]=dis
[u
]+edge
[i
].w
;pre
[v
]=i
;if(!inque
[v
]){que
.push(v
);inque
[v
]=1;}}} }if(pre
[t
]==-1) return 0;return 1;
}
ll
EK(){int flow
;ll ret
=0;while(spfa()){flow
=inf
;int x
=pre
[t
];while(x
!=-1){flow
=min(edge
[x
].f
,flow
);x
=pre
[edge
[x
].u
];}x
=pre
[t
];while(x
!=-1){edge
[x
].f
-=flow
;edge
[x
^1].f
+=flow
;ret
+=flow
*edge
[x
].w
;x
=pre
[edge
[x
].u
];}}return ret
;
}
int lx
[85],rx
[85],ly
[85],ry
[85];
void solve(int k
){memset(head
,-1,sizeof(head
));cnt
=0;memset(lx
+1,0,k
<<2),memset(ly
+1,0,k
<<2),memset(rx
+1,0x7f,k
<<2),memset(ry
+1,0x7f,k
<<2);for(int i
=1;i
<=m
;i
++){if(q
[i
].ch
=='L') lx
[q
[i
].b
+1]=max(lx
[q
[i
].b
+1],q
[i
].a
+1);if(q
[i
].ch
=='R'&&k
>q
[i
].b
) rx
[k
-q
[i
].b
]=min(rx
[k
-q
[i
].b
],q
[i
].a
-1);if(q
[i
].ch
=='D') ly
[q
[i
].b
+1]=max(ly
[q
[i
].b
+1],q
[i
].a
+1);if(q
[i
].ch
=='U'&&k
>q
[i
].b
) ry
[k
-q
[i
].b
]=min(ry
[k
-q
[i
].b
],q
[i
].a
-1);}for(int i
=2;i
<=k
;i
++) lx
[i
]=max(lx
[i
],lx
[i
-1]),ly
[i
]=max(ly
[i
],ly
[i
-1]);for(int i
=k
-1;i
;i
--) rx
[i
]=min(rx
[i
],rx
[i
+1]),ry
[i
]=min(ry
[i
],ry
[i
+1]);s
=0;t
=k
+n
+n
+k
+1;for(int i
=1;i
<=k
;i
++){add(s
,i
,1,0);for(int j
=1;j
<=n
;j
++){if(lx
[i
]<=p
[j
].x
&&p
[j
].x
<=rx
[i
]) add(i
,k
+j
,1,0);if(ly
[i
]<=p
[j
].y
&&p
[j
].y
<=ry
[i
]) add(k
+n
+j
,k
+n
+n
+i
,1,0);}add(k
+n
+n
+i
,t
,1,0);}for(int j
=1;j
<=n
;j
++) add(k
+j
,k
+n
+j
,1,p
[j
].val
);ans
=max(ans
,EK());
}
int main(){scanf("%d",&n
);for(int i
=1;i
<=n
;i
++)scanf("%d%d%lld",&p
[i
].x
,&p
[i
].y
,&p
[i
].val
);scanf("%d",&m
);for(int i
=1;i
<=m
;i
++)scanf("%s%d%d",&q
[i
].ch
,&q
[i
].a
,&q
[i
].b
);for(int k
=1;k
<=n
;k
++) solve(k
);printf("%lld\n",ans
);return 0;
}
總結
以上是生活随笔為你收集整理的[AGC031E] Snuke the Phantom Thief(网络流)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。