题目链接:http://acm.uestc.edu.cn/#/problem/show/88
You have a rectangular piece of paper that is divided into 1×1 cells, each of which has an integer value.
You want to perform a sequence of folds on the paper, where you may fold anywhere along an axis that is in between two rows or columns of the paper. After performing all the folds you want, the overlapping cells will be considered as a single cell, whose value is the sum of the individual cells.
You want the biggest number in the resulting piece of paper to be as large as possible, what is the biggest number you can get ?
Input
First line of the input is a single integer T(1≤T≤10), indicating there are T test cases. For each test case, the first line contains two integers, N and M (1≤N≤20,1≤M≤500), indicating the length and width of the paper. Then N lines followed, each line contains M integers xi(−104≤xi≤104), indicating the numbers in the original piece of paper.
Output
For each case,output Case #t: ret
in a single line, where t indicating the case number between 1 and T, and ret is the biggest number you can get in the resulting piece of paper.
Sample input and output
Sample Input | Sample Output |
---|---|
2 2 2 1 -2 3 -4 2 5 1 -2 -3 4 -5 6 -7 -8 9 -10 | Case #1: 4 Case #2: 20 |
Hint
- Of course, if you do not fold any cells, the value of each cell is its original value.
Explanation for the 2nd Case in Sample Input
Note that merging the overlapping cells only happens after all the folds, which means:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;
int main()
{
int t;
int n, m;
int a[30][520];
int cas = 0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int ans = -INF;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
scanf("%d",&a[i][j]);
if(a[i][j] > ans)
ans = a[i][j];
}
}
for(int i = 1; i < (1<<n); i++)//状态压缩行
{
int flag = 0;
int t1 = -1, t2 = -1;//记录前后行位置
for(int j = 0; j < n; j++)
{
if(i & (1<<j))
{
t1 = j;
if(t2>=0 && (t1-t2)%2 == 0)//行相差为偶数不行折叠
{
flag = 1;
break;
}
t2 = t1;
}
}
if(flag)
continue;
int sum[520];//每一列的和
memset(sum,0,sizeof(sum));
for(int k = 0; k < m; k++)//lie
{
for(int h = 0; h < n; h++)//hang
{
if(i & (1<<h))
sum[k] += a[h][k];
}
}
int dp[2];
dp[0] = dp[1] = -INF;
for(int j = 0; j < m; j++)
{
if(j & 1)//奇
{
dp[1] = max(dp[1],sum[j]);
dp[1] = max(dp[1],dp[0]+sum[j]);
}
else//偶
{
dp[0] = max(dp[0],sum[j]);
dp[0] = max(dp[0],dp[1]+sum[j]);
}
}
dp[1] = max(dp[1],dp[0]);
ans = max(ans,dp[1]);
}
printf("Case #%d: %d\n",++cas,ans);
}
return 0;
}
/*
99
1 1
-1
2 2
1 -2
3 -4
2 5
1 -2 -3 4 -5
6 -7 -8 9 -10
*/