HDU2732一个让我debug了一晚上的题目
Posted Butterflier
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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…………\n",now); for(int i = id[now];~i;i = e[i].pre) { int to = e[i].to; int cost = e[i].cost; // printf("\tdata : to = %d cost = %d flor[to] = %d\n",to,cost,flor[to]); if(flor[to] == 0 && cost > 0) { flor[to] = flor[now] + 1; q.push(to); // printf("\tNow flor[to] is %d\n",flor[to]); // printf("\tIN QUEUE %d\n",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\n",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…………\n",id1,id2); if(i - d < 0 || j - d < 0 || i + d >= n || j + d >= m) { add(id1,t,mp1[i][j] - ‘0‘); // printf("可跳出\n"); // printf("\tadd %d to %d c = %d\n",id1,t,mp1[i][j] - ‘0‘); } else { add(id1,id2,mp1[i][j] - ‘0‘); // printf("不可跳出\n"); // printf("\tadd %d to %d c = %d\n",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("\t连接临边 …… \n"); add(id2,k*m+p+1,inf); // printf("\t\tadd %d to %d c = inf",id2,k*m+p+1); } } } } if(mp2[i][j] == ‘L‘) { // printf("连接初始边\n"); // printf("add 0 to %d c = %d\n",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.\n"); else if(op == 1) printf("1 lizard was left behind.\n"); else if(op == 2) printf("2 lizards were left behind.\n"); else printf("%d lizards were left behind.\n",op); } return 0; }
看了上述内容,我一开始的错误是,第一次ok,第二次答案就错了,常规是没有初始化好东西,经过n次检查,该初始化的都初始化了,不该的也初始化了,还是不对
最后就是初始化不对
模拟之后发现,原来memset(flor数组)的时候只清空了sizeof(flor)的大小,一开始我开的大小是25,(黑脸!!!)
好了,说多了都是泪,找到了,AC了就是好的吧,以后注意!!!这些小细节!
以上是关于HDU2732一个让我debug了一晚上的题目的主要内容,如果未能解决你的问题,请参考以下文章
HDU 2732 Leapin' Lizards(拆点+最大流)