P1653疯狂的方格取数

背景

Due to the talent of talent123,当talent123做完NOIP考了两次的二取方格数和vijos中的三取方格数后,突发奇想....

描述

在一个宽M,长N的矩阵中,请你编一个程序,n次从矩阵的左上角走到矩阵的右下角,每到一处,就取走该处的数字,请你选择一
种走法使取得的数字的和最大,并输出其最大值。其中:3<=M<=20 M<=N<=100 1<=n<=10

如输入数据:
3 10 13

0 1 2 3 4 9 7 1 3 1
9 1 2 2 3 6 7 8 1 2
1 2 3 4 5 9 8 7 6 1
9 7 1 3 1 9 1 2 2 3
6 7 8 1 2 1 2 3 4 5
9 1 2 2 3 6 7 8 1 2
1 2 3 4 5 9 8 7 6 1
9 7 1 3 1 9 1 2 2 3
6 7 8 1 2 1 2 3 4 5
9 1 2 2 3 6 7 8 1 2
1 2 3 4 5 9 8 7 6 1
9 7 1 3 1 9 1 2 2 3
6 7 8 1 2 1 2 3 4 0
其中n=3
M=10
N=13
即当n=3时,就相当于是3取方格数。

对于以上的数据:
将输出:297
//注:如过你想到了无记忆性搜所的方法(不管你怎样优化),你可以直接放弃这道题了。

//提示1:动态规划如果用的是二位数组,规模为100*100000即可。

//提示2:如果你坚信自己的程序已经无可优化了,可有2个数据依然超时,那么告诉你,存在数据有M<n的情况!!!

格式

输入格式

第一行:三个整数:n M N
以下的N行每行M个数字,代表你要处理的矩阵。

输出格式

只有一行:你所取得的数字的和。

样例1

样例输入1[复制]

 
4 6 7
0 2 3 4 5 6
6 5 4 3 2 1
0 9 8 7 6 5
12 3 4 5 6 7
0 0 0 1 2 3
12 23 34 45 1 23
4 5 6 6 1 0

样例输出1[复制]

 
265

限制

共有10个测试数据,每个测试数据包含1个测试点,每个测试点的时间限制为2秒钟。

 

从左上角走到右下角是找一个增广路,然后我们要费用最大,最大费用最大流?边权取负不就变成最小费用最大流了。

也可以修改spfa。。。然后就好了

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<string>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #include<set>
12 #define inf 1000000000
13 #define maxn 50000+5
14 #define maxm 100+5
15 #define eps 1e-10
16 #define ll long long
17 #define for0(i,n) for(int i=0;i<=(n);i++)
18 #define for1(i,n) for(int i=1;i<=(n);i++)
19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22 using namespace std;
23 int n,m,k,mincost,tot=1,s,t,head[maxn],d[maxn],from[2*maxn],map[maxm][maxm];
24 bool v[maxn];
25 queue<int>q;
26 struct edge{int from,go,next,v,c;}e[2*maxn];
27 int read(){
28     int x=0,f=1;char ch=getchar();
29     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
30     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
31     return x*f;
32 }
33 void insert(int x,int y,int v,int c){
34     e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;
35     e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;
36 }
37 bool spfa(){
38     for (int i=s;i<=t;i++){v[i]=0;d[i]=-inf;}
39     q.push(s);d[s]=0;v[s]=1;
40     while(!q.empty()){
41         int x=q.front();q.pop();v[x]=0;
42         for (int i=head[x],y;i;i=e[i].next)
43             if(e[i].v&&d[x]+e[i].c>d[y=e[i].go]){
44                 d[y]=d[x]+e[i].c;from[y]=i;
45                 if(!v[y]){v[y]=1;q.push(y);}
46              }
47     }
48     return d[t]!=-inf;
49 }
50 void mcf(){
51     mincost=0;
52     while(spfa()){
53         int tmp=inf;
54         for(int i=from[t];i;i=from[e[i].from]) tmp=min(tmp,e[i].v);
55         mincost+=d[t]*tmp;
56         for(int i=from[t];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;}
57     }
58 }
59 int main(){
60     //freopen("input.txt","r",stdin);
61     //freopen("output.txt","w",stdout);
62     k=read();m=read();n=read();
63     for1(i,n)
64         for1(j,m){
65             int w=read();
66             insert(((i-1)*m+j)*2-1,((i-1)*m+j)*2,1,w);
67             insert(((i-1)*m+j)*2-1,((i-1)*m+j)*2,inf,0);
68             if(j<m)insert(((i-1)*m+j)*2,((i-1)*m+j+1)*2-1,inf,0);
69             if(i<n)insert(((i-1)*m+j)*2,(i*m+j)*2-1,inf,0);
70         }
71     s=0,t=((n-1)*m+m)*2+1;
72     insert(s,1,k,0);insert(t-1,t,inf,0);
73     mcf();
74     printf("%d\n",mincost);
75     return 0;
76 }
View Code

 

posted @ 2016-07-14 11:11  HTWX  阅读(139)  评论(0编辑  收藏  举报