《2174: Leapin' Lizards》

这题太妙了。

一开始一直在想怎么bfs和记忆化搜索。

正确的思路:把最外面看成源点,汇点对每个人建边,然后柱子的限制对自己拆点建边(限制做容量)。

然后超级汇点对每个人连边。最后要对满足条件的柱子之间建边即可。

这里输出巨坑。0 和 1 和 >1的输出都不一样,找了好久(出题人大气层)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 1e4 + 5;
const int M = 1e6 + 5;
const LL Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

int n,m,d,a[25][25];
int s,t,cnt = -1;
int head[N],dep[N],cur[N];
struct Node{int to,dis,next;}e[M<<2];
inline void add(int u,int v,int w)
{
    e[++cnt].to = v,e[cnt].dis = w,e[cnt].next = head[u],head[u] = cnt;
    e[++cnt].to = u,e[cnt].dis = 0,e[cnt].next = head[v],head[v] = cnt;
}
bool bfs()//分层
{
    queue<int> Q;
    memset(dep,-1,sizeof(dep));
    dep[s] = 0;
    Q.push(s);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int y = e[i].to,d = e[i].dis;
            if(dep[y] == -1 && d > 0)
            {
                dep[y] = dep[u]+1;
                Q.push(y);
            }
        }
    }
    return dep[t] != -1;
}
int dfs(int u,int flow)
{
    int nowflow = 0,k;
    if(u == t) return flow;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        cur[u] = i;//当前弧优化
        int y = e[i].to,d = e[i].dis;
        if((dep[y] == dep[u]+1) && d > 0)
        {
            if(k = dfs(y,min(flow-nowflow,d)))
            {
                e[i].dis -= k;
                e[i^1].dis += k;
                nowflow += k;
                if(nowflow == flow) break; 
            }
        }
    }
    if(nowflow == 0) dep[u] = -1;//炸点优化
    return nowflow;
}
LL solve()
{
    LL ans = 0;
    while(bfs())
    {
        for(int i=1;i<=n;++i) cur[i] = head[i];
        ans += dfs(s,INF);
    }
    return ans;
}
/*s - 0
st - i * m + j + 1;
to - i * m + j + 1 + 1000;
t - 2001;
*/
struct Point{int x,y;};
vector<Point> vec;
int main()
{
    int ca,tot = 0;ca = read();
    while(ca--)
    {
        n = read(),d = read();
        memset(head,-1,sizeof(head));
        cnt = -1;
        vec.clear();
        s = 0,t = 2001;
        for(int i = 0;i < n;++i) 
        {
            string ss;cin >> ss;
            m = ss.size();
            for(int j = 0;j < m;++j) a[i][j] = ss[j] - '0';
            for(int j = 0;j < m;++j)
            {
                if(a[i][j] != 0)
                {
                    add(i * m + j + 1,i * m + j + 1 + 1000,a[i][j]);//柱子自己的限制
                    if(min(i,abs(n - i) - 1) < d || min(j,abs(m - j) - 1) < d) add(i * m + j + 1 + 1000,t,INF);//满足条件的柱子向源点连
                    vec.push_back(Point{i,j});
                }
            }
        }
        int num = 0;
        for(int i = 0;i < n;++i)
        {
            string ss;cin >> ss;
            for(int j = 0;j < m;++j)
            {
                if(ss[j] == '.') continue;
                num++;
                add(s,i * m + j + 1,1);//汇点向全部人连.
            }
        }
        for(int i = 0;i < vec.size();++i)
        {
            int x1 = vec[i].x,y1 = vec[i].y;
            for(int j = i + 1;j < vec.size();++j)
            {
                int x2 = vec[j].x,y2 = vec[j].y;
                int dis = abs(x1 - x2) + abs(y1 - y2);
                if(dis > d) continue;
                add(x1 * m + y1 + 1 + 1000,x2 * m + y2 + 1,INF);
                add(x2 * m + y2 + 1 + 1000,x1 * m + y1 + 1,INF);
            }
        }
        LL ans = 1LL * num - solve();
        if(ans == 0) printf("Case #%d: no lizard was left behind.\n",++tot);
        else if(ans == 1) printf("Case #%d: 1 lizard was left behind.\n",++tot);
        else printf("Case #%d: %lld lizards were left behind.\n",++tot,ans);
    }
    system("pause");
    return 0;
}
/*
20
20 2
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
11111111111111111111
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
LLLLLLLLLLLLLLLLLLLL
*/
View Code

 

posted @ 2020-12-11 21:22  levill  阅读(98)  评论(0编辑  收藏  举报