【POJ

来源:互联网 发布:c语言内容有多少 编辑:程序博客网 时间:2024/06/10 13:47

On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking care that the rook moves only to the right or down. Kaka adds the number to SUM in each grid the rook visited, and replaces it with zero. It is not difficult to know the maximum SUM Kaka can obtain for his first travel. Now Kaka is wondering what is the maximum SUM he can obtain after his Kth travel. Note the SUM is accumulative during the K travels.

Input
The first line contains two integers N and K (1 ≤ N ≤ 50, 0 ≤ K ≤ 10) described above. The following N lines represents the matrix. You can assume the numbers in the matrix are no more than 1000.

Output
The maximum SUM Kaka can obtain after his Kth travel.

Sample Input
3 2
1 2 3
0 2 1
1 4 2
Sample Output
15
题意 :一个矩阵,每个位置上有点权,让你现在从左上角运动到右下角 走k次,每个点可以走多次,但是每个位置的点权只可以获得一次。问k次之后得到的最大的值。

分析 :我喜欢这样用矩阵来建图的题,很有感觉。HDU的这个题的变形
这两个题目,我都是用的拆点,拆的两个点之间的边来表示经过这个点获得的分数。
下面看图【图画的有点乱,TAT】
这里写图片描述
总共需要将n*n个点进行拆点,图中我假设从起点到终点之间只有一个点。
S->1的边流量为k,表明可以走k次旅行,费用为0。
1 -> 1’ 2 -> 2’ 等等即图中的绿色的边,其流量为1,费用为1 . 2. 等等位置的权值, 意思就是如果要经过这个边就 表明是获得这个位置的分数,流量限制为1表示只能够获得一次分数。
1->2 边流量为inf,费用为0,表明可以从1走到2但是不获得分数。
2->3同上理。
1’-> 2 流量为inf,费用为0,表明获得完1分数之后仍然可以走到2这个点。
2 ’ -> 3 同上理。
3->T 和3’->T 流量都为inf,费用为0,分别表明可以不获得分数到达终点的旅行,获得分数仍然可以到达终点的旅行。
一条流就代表一个旅行。
代码

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<queue>using namespace std;#define  LL long long#define fread() freopen("in.txt","r",stdin)#define fwrite() freopen("out.txt","w",stdout)#define CLOSE() ios_base::sync_with_stdio(false)const int MAXN = 6000+11;const int MAXM = 500000+11;const int mod = 1e9+7;const int inf = 0x3f3f3f3f;struct Edge {    int from,to,next,cap,flow,cost;}edge[MAXM];int head[MAXN],top;void init(){    memset(head,-1,sizeof(head));    top=0;} void addedge(int a,int b,int w,int c){    edge[top].from=a,edge[top].to=b,edge[top].cap=w,edge[top].flow=0,edge[top].cost=c,edge[top].next=head[a];    head[a]=top++;    edge[top].from=b,edge[top].to=a,edge[top].cap=0,edge[top].flow=0,edge[top].cost=-c,edge[top].next=head[b];    head[b]=top++;}int n,k,m;int S,T;int mp[55][55];void getmap(){     S=0,T=n*m*2+1;     int temp=n*m;     for(int i=1;i<=n;i++){        for(int j=1;j<=m;j++){            scanf("%d",&mp[i][j]);         }     }     addedge(S,1,k,0);     for(int i=1;i<=n;i++){        for(int j=1;j<=m;j++){            addedge((i-1)*n+j,(i-1)*n+j+temp,1,-mp[i][j]);//自己和对称的自己的边            int nx=i+1;int ny=j;            if(nx<1||ny<1||nx>n||ny>m) ;            else {                addedge(((i-1)*n+j),(nx-1)*n+ny,inf,0);// 不获得分数也可以到达的路                addedge(((i-1)*n+j)+temp,(nx-1)*n+ny,inf,0);//获得分数仍然可以到达的路             }            nx=i;ny=j+1;            if(nx<1||ny<1||nx>n||ny>m)  ;            else {                addedge(((i-1)*n+j),(nx-1)*n+ny,inf,0);                addedge(((i-1)*n+j)+temp,(nx-1)*n+ny,inf,0);             }         }     }     addedge(n*m,T,inf,0);  //不获得分数也可以到达终点的路     addedge(n*m+temp,T,inf,0);/、获得分数也可以到达终点的路}bool vis[MAXN];int dis[MAXN];int pre[MAXN];bool spfa(int s,int e){    queue<int>Q;    memset(vis,0,sizeof(vis));    memset(dis,0x3f,sizeof(dis));    memset(pre,-1,sizeof(pre));    dis[s]=0;vis[s]=1;Q.push(s);    while(!Q.empty()){        int now=Q.front();Q.pop();vis[now]=0;        for(int i=head[now];i!=-1;i=edge[i].next){            Edge  e=edge[i];            if(e.cap>e.flow&&dis[e.to]>dis[now]+e.cost){                dis[e.to]=dis[now]+e.cost;                pre[e.to]=i;                if(!vis[e.to]){                    vis[e.to]=1;                    Q.push(e.to);                }            }        }    }    return pre[e]!=-1;}int MCMF(int s,int t,int &cost,int &flow){    flow=cost=0;    while(spfa(s,t)){        int Min=inf;        for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){            Min=min(Min,edge[i].cap-edge[i].flow);         }         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){             edge[i].flow+=Min;             edge[i^1].flow-=Min;             cost+=edge[i].cost*Min;         }         flow+=Min;     }}int main(){    CLOSE();//  fread();//  fwrite();    while(scanf("%d%d",&n,&k)!=EOF){        init(); m=n;        getmap();        int flow,ans;        MCMF(S,T,ans,flow);        //printf("%d\n",flow);        printf("%d\n",-ans);    }    return 0;}
原创粉丝点击