Wannafly挑战赛26-B 冥土追魂

地址:https://www.nowcoder.com/acm/contest/212/B

思路:对于行列选取,是选择所有行中的最大值的最小值,当是并不能用贪心来做,例如

2 2 2
7 8
1 9

如果用贪心的话就是7+8=15,但是最小值是1+9=10

对于a[i][j]行按照由大到小排序,列按照行总和由小到大排序,选取顺序应该是以每次选择一整行来考虑的,即若k>=m,则选取前m个数一定是选取一整行的数的,可以这样考虑借鉴博客Wannafly挑战赛26: B. 冥土追魂(思维题)

假设第1行选择了前x个数字, 第2行选择了前y个数字,且x, y<m(都没选满一行)

首先肯定a[2][y+1]>a[1][x] (如果a[2][y+1]<=a[1][x]的话,那么选择a[2][y+1]更优,而不会选a[1][x]了)   那么可以得出a[2][y+1]>a[1][x] → a[2][y]>a[1][x] → a[2][y]>a[1][x+1],这样的话如果第二行选择前y-1个数字,第一行选择前x+1个一定更优

t1=k/m,t2=k%m, 那么可以对于t2可以枚举所有行,在取前t1(不包含t2选取行)行,保存最小值即可

Code :

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

const int MAX_N=1005;
const int MAX_M=1005;
int n,m,s;
int a[MAX_N][MAX_M];
struct node{
	LL Sum[MAX_M];
	int id;
	bool operator<(const node &p)const{
		return Sum[m]<p.Sum[m];
	}
}d[MAX_N];

bool cmp(const int &a,const int &b){
	return a>b;
}
int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n>>m>>s){
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				cin>>a[i][j];
		for(int i=1;i<=n;++i)
			sort(a[i]+1,a[i]+m+1,cmp);
		for(int i=1;i<=n;d[i].id=i++)
			for(int j=1;j<=m;++j)
				d[i].Sum[j]=d[i].Sum[j-1]+a[i][j];
		sort(d+1,d+n+1);
		LL ans=1e18,num;
		for(int i=1;i<=n;++i)
		{
			num=d[i].Sum[s%m];
			for(int j=1,t=s/m;j<=n&&t>0;++j)
			{
				if(i==j&&s%m)	continue;
				num+=d[j].Sum[m];
				--t;
			}
			ans=min(ans,num);
		}
		cout<<ans<<endl;
	}
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值