深海机器人问题

来源:互联网 发布:以史为镜,可以知兴替 编辑:程序博客网 时间:2024/04/28 16:19

这里写图片描述
这题的题面描述。。有点问题。。坐标写的很乱。
这道题其实和著名DP问题方格取数很像qwq
我们发现机器人可以重复经过边,但只能对答案贡献一次,所以两点间连两条边。一条是容量1带的费用。
另一条没费用容量INF。用拆点吗?不用的。因为这个权值是走过边会有,所以这题中不用拆点。

起点连S容量机器人,终点连T容量机器人。注意算好点的坐标别发生计算错误调半天这样的傻事qwq。

#include<bits/stdc++.h>using namespace std;const int MAXN=1e5+5;const int INF=1e9+7;struct edge{    int u,to,next,w,c;}e[MAXN<<1];int head[MAXN],cnt=1;inline void add(int u,int v,int w,int cost){    e[++cnt]=(edge){u,v,head[u],w,cost},head[u]=cnt;    e[++cnt]=(edge){v,u,head[v],0,-cost},head[v]=cnt;}int p,q,a,b,s,t;bool vis[MAXN];int dis[MAXN],pre[MAXN];queue<int>qq;bool SPFA(int x){    memset(vis,0,sizeof(vis));    memset(pre,0,sizeof(pre));    for(int i=s;i<=t;i++)dis[i]=-INF;    qq.push(x);vis[x]=1;dis[x]=0;    while(qq.size()){        int u=qq.front();qq.pop();        vis[u]=0;        for(int i=head[u];i;i=e[i].next){            int v=e[i].to,w=e[i].c;            if(e[i].w){                if(dis[u]+w>dis[v]){                    dis[v]=dis[u]+w;pre[v]=i;                    if(!vis[v]){                        qq.push(v);                        vis[v]=1;                    }                }            }        }    }    if(dis[t]==-INF)return 0;    return 1;} int MC(){    int ans=0;    while(SPFA(s)){        int tem=INF;        for(int i=pre[t];i;i=pre[e[i].u]){            tem=min(tem,e[i].w);        }        for(int i=pre[t];i;i=pre[e[i].u]){            e[i].w-=tem;e[i^1].w+=tem;            ans+=tem*e[i].c;        }    }    return ans;}int main(){    int tem;    scanf("%d%d%d%d",&a,&b,&p,&q);    p++;q++;    s=0,t=p*q+1;//(x,y)按照 y进制 一个y是一行x     for(int i=0;i<p;i++){//坐标为(j,i)        for(int j=0;j<q-1;j++){            int now=i*q+j+1;            scanf("%d",&tem);            add(now,now+1,1,tem);            add(now,now+1,INF,0);        }     }    for(int i=0;i<q;i++){//坐标为(i,j)        for(int j=0;j<p-1;j++){            int now=j*q+i+1;            scanf("%d",&tem);            add(now,now+q,1,tem);            add(now,now+q,INF,0);        }    }    for(int i=1;i<=a;i++){        int k,x,y;        scanf("%d%d%d",&k,&y,&x);        int now=y*q+x+1;    //  cout<<now<<"ok"<<endl;        add(s,now,k,0);    }    for(int i=1;i<=b;i++){//横行q个点,纵列p个点         int k,x,y;        scanf("%d%d%d",&k,&y,&x);        int now=y*q+x+1;    //  cout<<"p:"<<p<<endl;    //  cout<<"q:"<<q<<endl;    //          cout<<now<<"ok"<<endl;        add(now,t,k,0);    }    printf("%d\n",MC());    return 0;}