方格填数
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 628 Accepted Submission(s): 168
Problem Description
给你一个N*N的方格,里面都是非负整数(小于32768),我们定义这个方格的总和为:其中的任何一个S*S(1<=S<=N)的子方格中的数字的总和。由于中间有K(0<=K<=N*N)个单位方格中的数字是0,因此现在给定你M(K<=M&&M<=10000)个正整数(小于32768),你可以从中选择K个,来填入原来的N*N的值为0的单位方格中,从而最大化的增加我们定义的方格的总和。
Input
这里有T组测试数据,第一行输入T,T<=100。对于测试数据,先输入一个N(N<=30),然后输入一个N*N的矩阵,中间含0的元素,然后给定一个M,后一行输入M个正整数。
Output
对于每组测试数据,输出能够最大的增加的值。
Sample Input
1 3 1 2 3 4 0 2 0 2 7 4 2 9 4 7
Sample Output
75
Author
wangye
枚举每一个点,以这个点为左上侧端点的所有情况都列出来,然后求出所有的点的权值,然后再贪心
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y;
int val;
}p[990];
int vis[33][33],map[33][33],num[999];
bool cmp(node s1,node s2)
{
return s1.val>s2.val;
}
bool cmp2(int a,int b)
{
return a>b;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,k;
scanf("%d",&n);
int cnt=0;
memset(map,0,sizeof(map));
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==0)
{
p[cnt].x=i;
p[cnt++].y=j;
}
}
}
scanf("%d",&k);
for(int i=0;i<k;i++)
scanf("%d",&num[i]);
sort(num,num+k,cmp2);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int L=min(n-i,n-j);//枚举出所有的长度
for(int l=1;l<=L+1;l++)
{
for(int aa=i;aa<l+i;aa++)
{
for(int bb=j;bb<l+j;bb++)
{
vis[aa][bb]++;
}
}
}
}
}
for(int i=0;i<cnt;i++)
p[i].val=vis[p[i].x][p[i].y];
sort(p,p+cnt,cmp);
__int64 sum=0;
for(int i=0;i<cnt;i++)
sum+=p[i].val*num[i];
printf("%I64d\n",sum);
}
return 0;
}