hdoj--1794--方格填数(规律)

方格填数

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;
}


你可能感兴趣的:(hdoj--1794--方格填数(规律))