HRBUST 1214 方格取数

方格取数

Time Limit: 1000ms

Memory Limit: 65535KB

This problem will be judged on HRBUST. Original ID: 1214
64-bit integer IO format: %lld      Java class name: Main

设有N*N的方格图(N<=10),我们将其中的某些方格中填入正整数,而其他的方格中则放人数字0。如下图所示(见样例 ,黄色和蓝色分别为两次走的路线,其中绿色的格子为黄色和蓝色共同走过的):


A
             
    13     6    
        7      
      14        
  21       4    
    15          
  14            
             
B

某人从图的左上角的A点出发,可以向下行走,也可以向右走,直到到达右下角的B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。此人从A点到B点共走两次,试找出2条这样的路径,使得取得的数之和为最大

Input

有多组测试数据,每组格式如下:
    第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。

Output

与输入对应,有多组输出,每组只需输出一个整数,表示2条路径上取得的最大的和。

Sample Input

8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0

Sample Output

67

Source

NOIp2000提高组

解题:拆点费用流。见http://www.cnblogs.com/crackpotisback/p/3971435.html

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <climits>
 7 #include <vector>
 8 #include <queue>
 9 #include <cstdlib>
10 #include <string>
11 #include <set>
12 #include <stack>
13 #define LL long long
14 #define pii pair<int,int>
15 #define INF 0x3f3f3f3f
16 using namespace std;
17 const int maxn = 400;
18 struct arc{
19     int v,w,f,next;
20     arc(int x = 0,int y = 0,int z = 0,int nxt = 0){
21         v = x;
22         w = y;
23         f = z;
24         next = nxt;
25     }
26 };
27 arc e[1000];
28 int head[maxn],d[maxn],p[maxn],S,T,n,mp[15][15],tot;
29 bool in[maxn];
30 queue<int>q;
31 void add(int u,int v,int w,int f){
32     e[tot] = arc(v,w,f,head[u]);
33     head[u] = tot++;
34     e[tot] = arc(u,-w,0,head[v]);
35     head[v] = tot++;
36 }
37 bool spfa(){
38     for(int i = 0; i < maxn; i++){
39         d[i] = INF;
40         in[i] = false;
41         p[i] = -1;
42     }
43     while(!q.empty()) q.pop();
44     d[S] = 0;
45     in[S] = true;
46     q.push(S);
47     while(!q.empty()){
48         int u = q.front();
49         q.pop();
50         in[u] = false;
51         for(int i = head[u]; ~i; i = e[i].next){
52             if(e[i].f > 0 && d[e[i].v] > d[u] + e[i].w){
53                 d[e[i].v] = d[u] + e[i].w;
54                 p[e[i].v]= i;
55                 if(!in[e[i].v]){
56                     in[e[i].v] = true;
57                     q.push(e[i].v);
58                 }
59             }
60         }
61     }
62     return p[T] > -1;
63 }
64 int solve(){
65     int tmp = 0,minV;
66     while(spfa()){
67         minV = INF;
68         for(int i = p[T]; ~i; i = p[e[i^1].v])
69             minV = min(minV,e[i].f);
70         for(int i = p[T]; ~i; i = p[e[i^1].v]){
71             e[i].f -= minV;
72             e[i^1].f += minV;
73             tmp += minV*e[i].w;
74         }
75     }
76     return tmp;
77 }
78 int main() {
79     int x,y,w;
80     while(~scanf("%d",&n)){
81         memset(mp,0,sizeof(mp));
82         memset(head,-1,sizeof(head));
83         S = tot = 0;
84         T = n*n*2+1;
85         while(scanf("%d %d %d",&x,&y,&w),x||y||w) mp[x][y] = w;
86         for(int i = 1; i <= n; i++){
87             for(int j = 1; j <= n; j++){
88                 add(n*(i-1)+j,n*(i-1)+j+n*n,-mp[i][j],1);
89                 add(n*(i-1)+j,n*(i-1)+j+n*n,0,INF);
90                 if(i < n) add(n*(i-1)+j+n*n,n*i+j,0,INF);
91                 if(j < n) add(n*(i-1)+j+n*n,n*(i-1)+j+1,0,INF);
92             }
93         }
94         add(S,1,0,2);
95         add(n*n*2,T,0,2);
96         printf("%d\n",-solve());
97     }
98     return 0;
99 }

时间: 2024-10-08 20:27:12

HRBUST 1214 方格取数的相关文章

hdu 1565 方格取数(2)(网络流之最大点权独立集)

题目链接:hdu 1565 方格取数(2) 题意: 有一个n*m的方格,每个方格有一个数,现在让你选一些数.使得和最大. 选的数不能有相邻的. 题解: 我们知道对于普通二分图来说,最大独立点集 + 最小点覆盖集 = 总点数,类似的,对于有权的二分图来说,有: 最大点权独立集 + 最小点权覆盖集 = 总点权和, 这个题很明显是要求 最大点权独立集 ,现在 总点权 已知,我们只要求出来 最小点权覆盖集 就好了,我们可以这样建图, 1,对矩阵中的点进行黑白着色(相邻的点颜色不同),从源点向黑色的点连一

P1004 方格取数

P1004 方格取数 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 0 0 0 0 0 7 0 0 0 0 0 0 14 0 0 0 0 0 21 0 0 0 4 0 0 0 0 15 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . B 某人从图的左上角的A点出发,可以向下行走,也可以向右走,直到到达右下角

hdoj 1569 方格取数(2) 【最小割】 【最大点权独立集】

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5589    Accepted Submission(s): 1741 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

1475: 方格取数

1475: 方格取数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 578  Solved: 309[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一个正整数.从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大. Input 第一行一个数n:(n<=30) 接下来n行每行n个数描述一个方阵 Output 仅一个数,即最大和 Sample Input 2 1 2

hdu 1569 方格取数(2) 网络流 最大点权独立集

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5146    Accepted Submission(s): 1610 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

HDU 1565 方格取数(1) (状态压缩 DP)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5779    Accepted Submission(s): 2194 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

HDU 1565 方格取数(1)(状压dp)

感觉这道题目的数据比较水啊,程序的时间复杂度为1711^2*20竟然也可以过掉....其他的就是状压了啊,注意需要滚动一下啊.... 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5701    Accepted Submission(s): 2159 Problem Description 给你一个n*n的格子的棋

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质

hdu 4859 最大点权独立集的变形(方格取数的变形)

/*刚开始不会写,最大点权独立集神马都不知道,在潘神的指导下终于做出来,灰常感谢ps: 和方格取数差不多奇偶建图,对于D必割点权为0,对于.必然不割点权为inf.然后和方格取数差不多的建图 .--.||E权值为2,,.||E--D权值为0. 最大点权独立集=sum-最小点权覆盖. */ #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define inf 0x3ffff