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了就是好的吧,以后注意!!!这些小细节!

  • 相关阅读:
    面向对象---工厂模式
    [转]Caffe 安装配置(CentOS + 无GPU)
    [转]Centos6.5+CUDA6.5+caffe安装配置及可能遇到问题解答
    [转]Caffe安装过程记录(CentOS,无独立显卡,无GPU)
    [转]LIBRARY_PATH和LD_LIBRARY_PATH环境变量的区别
    [转]centos 6.5安装caffe
    [转]CentOS编译安装GIMP
    [转]Snappy压缩库安装和使用之一
    [转]拍照怎么搜题?(下)
    [转]拍照怎么搜题?(上)
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9688860.html
Copyright © 2011-2022 走看看