zoukankan      html  css  js  c++  java
  • HDU2732一个让我debug了一晚上的题目

    思路都理解了,清晰了,就是代码不对,还是有些小地方自己注意不到,即使就在你的眼前也不易发现的那种

    Description:

      也是一个最大流的构图,没相出来,或者说想简单了也是标记点1 至 n * m是层有物品加边0 - i - 1
    XXXXX

    我想的是能调跳到安全点的加边i - t - 承受次数
    并且还要互相连边,表示可以跳到,但是这样就把限制跳的次数扩大了不是
    XXXXX
    后来就没再想出来,看看题解后,真是巧妙,拆点
    把一个点拆成两个i j 必须从i跳进,跳进后,必须跳到j,限制跳跃次数,从j
    上往别的地方跳,就没有了限制,完美的解决了限制次数的问题
    所以S = 0;1 - n * m ; n * m + 1 - 2 * n * m;T = 2 * n * m + 1;
    这四个部分
    第一二部分相连:表示柱子上有没有跳跃的动物,限流为1(因为一个柱子上只能有一个)

    如果第二部分可以直接跳出

      那么就第二四部分相连,权值为限制跳跃次数,相当于贪心吧,其实也很合理,来到了这里,能走为什么不走呢,最大流  肯定是走的情况

    如果不能走
      第二三部分一一相连:柱子限制的跳跃次数
      第三二部分相连:表示在跳跃范围内,能够跳到的地方(注意距离的计算为曼哈顿距离)限制为inf

    基础准备 + 添边 操作

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define inf (1 << 28)
    using namespace std;
    const int maxn = 10005;
    const int maxm = 50005;
    struct edge{
        int to,cost,pre;
    }e[maxm];
    char mp1[25][25];
    char mp2[25][25];
    int flor[maxn];
    int cur[maxn];
    int id[maxn],cnt;
    int n,d,all;
    queue<int>q;
    void init()
    {
        cnt = 0;
        all = 0;
        memset(id,-1,sizeof(id));
        while(q.size())q.pop();
    }
    void add(int from,int to,int cost)
    {
        e[cnt].to = to;
        e[cnt].cost = cost;
        e[cnt].pre = id[from];
        id[from] = cnt++;
        swap(from,to);
        e[cnt].to = to;
        e[cnt].cost = 0;
        e[cnt].pre = id[from];
        id[from] = cnt++;
    }
    

     我熟悉的DInic算法(这次debug见到了五花八门的Dinic,嘤嘤嘤)从我的中间输出来看,我debug中是多么的绝望,都当成模拟来做了

    bool bfs(int s,int t)
    {
        memset(flor,0,sizeof(flor));
        flor[s] = 1;
        while(q.size())q.pop();
        q.push(s);
        while(q.size())
        {
            int now = q.front();
            q.pop();
    //        printf("processing %d…………
    ",now);
            for(int i = id[now];~i;i = e[i].pre)
            {
                int to = e[i].to;
                int cost = e[i].cost;
    //            printf("	data : to = %d cost = %d flor[to] = %d
    ",to,cost,flor[to]);
                if(flor[to] == 0 && cost > 0)
                {
                    flor[to] = flor[now] + 1;
                    q.push(to);
    //                printf("	Now flor[to] is %d
    ",flor[to]);
    //                printf("	IN QUEUE %d
    ",to);
                    if(to == t)return true;
                }
            }
        }
        return false;
    }
    int dfs(int s,int t,int f)
    {
        if(s == t || f == 0) return f;
        int ret = f;
        for(int &i = cur[s];~i;i = e[i].pre)
        {
            int to = e[i].to;
            int cost = e[i].cost;
            int d;
            if(cost > 0 && flor[to] == flor[s] + 1 && (d = dfs(to,t,min(f,cost))))
            {
                e[i].cost -= d;
                e[i^1].cost += d;
                ret -= d;
                if(ret == 0)break;
            }
        }
        if(ret == f)flor[s] = 0;
        return f - ret;
    }
    int dinic(int s,int t)
    {
        int ret = 0;
        while(bfs(s,t))
        {
            memcpy(cur,id,sizeof(id));
            ret += dfs(s,t,inf);
        }
        return ret;
    }
    

     按照建图思想的加边操作

    int main()
    {
        int cas = 0;
        int t,m;
        scanf("%d",&t);
        while(t--)
        {
            init();
            scanf("%d%d",&n,&d);
            for(int i = 0;i < n;++i)
            {
                scanf("%s",mp1[i]);
            }
            m = strlen(mp1[0]);
            for(int i = 0;i < n;++i)
            {
                scanf("%s",mp2[i]);
            }
            int t = 2 * n * m + 1;
            //printf("s = 0 t = %d n = %d m = %d
    ",t,n,m);
            for(int i = 0;i < n;++i)
            {
                for(int j = 0;j < m;++j)
                {
                    int id1 = i*m+j+1;
                    int id2 = id1 + n*m;
                    if(mp1[i][j] - '0' > 0)
                    {
    
                        //printf("Processing %d %d…………
    ",id1,id2);
                        if(i - d < 0 || j - d < 0 || i + d >= n || j + d >= m)
                        {
                            add(id1,t,mp1[i][j] - '0');
    //                        printf("可跳出
    ");
    //                        printf("	add %d to %d c = %d
    ",id1,t,mp1[i][j] - '0');
                        }
                        else
                        {
                            add(id1,id2,mp1[i][j] - '0');
    //                        printf("不可跳出
    ");
    //                        printf("	add %d to %d c = %d
    ",id1,id2,mp1[i][j] - '0');
    
                            for(int k = 0;k < n;k++)
                            {
                                for(int p = 0;p < m;p++)
                                {
                                    if(k == i && p == j)continue;
                                    if(abs(i-k) + abs(j - p) > d)continue;
    //                                printf("	连接临边 …… 
    ");
                                    add(id2,k*m+p+1,inf);
    //                                printf("		add %d to %d c = inf",id2,k*m+p+1);
                                }
                            }
                        }
                    }
                    if(mp2[i][j] == 'L')
                    {
    //                    printf("连接初始边
    ");
    //                    printf("add 0 to %d c = %d
    ",id1,1);
                        add(0,id1,1);
                        all++;
                    }
                }
            }
    
            int s = dinic(0,t);
            int op = all - s;
    //        cout<<all<< " " << s<<endl;
            printf("Case #%d: ",++cas);
            if(op == 0)
                printf("no lizard was left behind.
    ");
            else if(op == 1)
                printf("1 lizard was left behind.
    ");
            else if(op == 2)
                printf("2 lizards were left behind.
    ");
            else
                printf("%d lizards were left behind.
    ",op);
        }
    
        return 0;
    }
    

    看了上述内容,我一开始的错误是,第一次ok,第二次答案就错了,常规是没有初始化好东西,经过n次检查,该初始化的都初始化了,不该的也初始化了,还是不对

    最后就是初始化不对

    模拟之后发现,原来memset(flor数组)的时候只清空了sizeof(flor)的大小,一开始我开的大小是25,(黑脸!!!)

    好了,说多了都是泪,找到了,AC了就是好的吧,以后注意!!!这些小细节!

  • 相关阅读:
    UVa 1354 天平难题 (枚举二叉树)
    广西邀请赛总结
    UVa 12118 检查员的难题 (dfs判连通, 构造欧拉通路)
    UVA
    Uva 127 "Accordian" Patience (模拟)
    UVA 10539 Almost Prime Numbers( 素数因子)
    HDU 1272 小希的迷宫(并查集)
    HDU 1213 How Many Tables (并查集)
    POJ 2236 Wireless Network(并查集)
    HDU 1233 还是畅通工程 ( Kruskal或Prim)
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9688860.html
Copyright © 2011-2022 走看看