1. 程式人生 > >[貪心] 冥土追魂 Wannafly挑戰賽26

[貪心] 冥土追魂 Wannafly挑戰賽26

連結:https://www.nowcoder.com/acm/contest/212/B
來源:牛客網
 

冥土追魂

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 524288K,其他語言1048576K
64bit IO Format: %lld

題目描述

有一天 Misaka 和 Kuroko 在玩一個關於冥土追魂的遊戲....
Misaka和Kuroko在一個 n x m 的棋盤上玩遊戲,每個格子上都放著一些呱太。遊戲共進行 k 回合,每一回合 Kuroko會選**有呱太**的一行 i,在這之後Misaka會選擇一列 j ,並拿走格子 (i, j) 上的所有呱太,Misaka希望自己拿走的呱太儘可能多,而Kuroko不想讓Misaka拿走很多呱太,所以她希望拿走的呱太儘可能少。
在一旁圍觀的恆溫死神希望預測結果,請你預測在雙方都採取最優策略的情況下,Misaka最終能拿走呱太的數量。

輸入描述:

第一行三個數 n, m, k。 
接下來 n 行,每行 m 個數,第 i 行第 j 個數表示棋盤第 i 行第 j 列上的呱太數量 ai,j。

輸出描述:

輸出共一個數,表示在你的預測下,Misaka最終能拿走呱太的數量。

示例1

輸入

複製

3 2 4
5 7
3 2
8 5

輸出

複製

17

備註:

1≤ n, m ≤ 1000, 1 ≤ k ≤ n x m, 1 ≤ ai,j ≤ 109
一行選完時最優
先選取 k / m 行, 再選取 k % m 個
如不能整除 列舉不取完的行, 在剩下的行中取和最小的 k / m 行

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int mn = 1010;

int a[mn][mn];
struct node
{
	int id;
	ll sum;
} s[mn];
bool cmp(const node& a, const node& b)
{
	return a.sum < b.sum;
}

int main()
{
	int n, m, k;
	scanf("%d %d %d", &n, &m, &k);
	for (int i = 1; i <= n; i++)
	{
		s[i].id = i;
		for (int j = 1; j <= m; j++)
		{
			scanf("%d", &a[i][j]);
			s[i].sum += a[i][j];
		}
		sort(a[i] + 1, a[i] + m + 1, greater<int>());
	}
	sort(s + 1, s + n + 1, cmp);

	ll ans = 1e18;
	int p = k / m, q = k % m;
	if (q == 0)
	{
		ans = 0;
		for (int i = 1; i <= p; i++)
			ans += s[i].sum;
	}
	else if (q != 0)
	{
		for (int i = 1; i <= n; i++)
		{
			ll res = 0;
			for (int j = 1; j <= q; j++)
				res += a[s[i].id][j];
				
			int t = p;
			for (int j = 1; j <= t; j++)
			{
				if (j == i)
				{
					t++;
					continue;
				}
				res += s[j].sum;
			}
			ans = min(ans, res);
		}
	}
	printf("%lld\n", ans);
	
	return 0;
}