您的位置:首页 > 其它

Facebook Hacker Cup 2017 Round 1 Pie Progress

2017-01-28 18:05 197 查看


Facebook Hacker Cup 2017 Round 1

Some pies are sweet, full of fruit and jam and sugar.
Some pies are savory, full of meat and potatoes and spices.
Some pies are in fact not pies at all but tarts or galettes. This probably won't stop you from eating them.
Every single day for N days, you're determined to eat a pie for dinner. Every morning, you'll take a trip to your local pie shop, and buy 0 or more of their pies. Every night, you'll eat one pie
that you've bought. Pies never go bad, so you don't need to eat a pie on the same day that you bought it. You may instead eat one that you purchased on an earlier day.
On the ith day, the shop has M pies for sale, with the jth of these pies costing Ci,j dollars. You can choose to buy any (possibly empty) subset of them.
However, this shop has measures in place to protect itself against crazy pie fanatics buying out its products too quickly. In particular, if you buy p pies on a single day, you must pay an additional tax of p2 dollars.

Input

Input begins with an integer T, the number of times you go on a pie-eating spree. For each case, there is first a line containing two space-separated integers, N and M.
Then, N lines follow, each containing M space-separated integers. The jth integer on the ith line is Ci,j.

Output

For the ith case, print a line containing "Case #i: " followed by the minimum you need to pay to eat a pie every day.

Constraints

1 ≤ T ≤ 100 

1 ≤ NM ≤ 300 

1 ≤ Ci,j ≤ 1,000,000 

Explanation of Sample

In the first case, you should buy both pies on the first day, for a total cost of 1 + 1 + 22 = 6. On the second day you should buy one pie for 100 + 12 = 101. On the third day you can eat one
of the spare pies you bought on the first day.
In the third case, you should buy and eat the cheapest pie every day, for a daily cost of 1 + 12 = 2, and a total cost of 10.
In the fourth case, one possible solution is to buy two pies on the first day (1 + 1 + 22 = 6), two pies on the second day (2 + 2 + 22 = 8), and one pie on the third day (3 + 12 =
4) for a total cost of 18. On the fourth and fifth days you can eat your two spare pies from the first and second days.

题意:一家买馅饼的店,第i 天,种类为j 的馅饼售价Ci,j元,问要想每天都有一个馅饼吃,最少要花多少钱。馅饼可以永久存放不会坏,所以可以提前买很多,同时每天买p个馅饼需要交税p*p。

思路:动态规划,状态定义 dp[i][j]  代表前i天,买j个馅饼所要花费的最少金钱数。即dp

就是最终的答案了。

转移方程的思路:

1.对于第一天,当然可以选择买1~m个,要使得价钱最低,把价钱从小到大排序即可满足。

2.不是第一天的情况,当前天枚举买的馅饼数目j,同时枚举j里面有k个馅饼是当前天买的,j-k个是前面提前买的。

dp[i][j] = min(dp[i][j], dp[i-1][j - k] + k^2 + k个馅饼的最小价钱)

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <math.h>
#define INF 0x3f3f3f3f
const int N = 310;
using namespace std;
int rec

;
int dp

;
int sum

;
void run()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
scanf("%d", rec[i] + j);
sort(rec[i] + 1, rec[i] + 1 + m);
}

memset(dp, INF, sizeof(dp));
memset(sum, 0, sizeof(sum));

dp[1][1] = rec[1][1] + 1;
sum[1][1] = rec[1][1];
for (int i = 2; i <= m; i++)
{
sum[1][i] = sum[1][i-1] + rec[1][i];
dp[1][i] = sum[1][i] + i*i;
}
//看了别人的代码并没有开sum数组,仔细分析一下
//sum数组其实是不必开的,因为使用时每种求和也
//是只用了一次,用时用一个变量存储之前计算的结果就好了
//不必多开个数组
for (int i = 2; i <= n; i++)
{
sum[i][1] = rec[i][1];
for (int j = 2; j <= m; j++)
sum[i][j] = sum[i][j-1] + rec[i][j];
}

for (int i = 2; i <= n; i++)
for (int j = i; j <= n; j++)
for (int k = 0; k <= j && k <= m; k++)//最多m个馅饼,所以当前k最多是m,j-k要大于等于0
{                                    //所以k要小于等于j
dp[i][j] = min(dp[i][j], dp[i-1][j - k] + k*k + sum[i][k]);
}
printf("%d\n", dp

);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r" ,stdin);
#endif
freopen("out.txt","w",stdout);
int T, cas = 1;

scanf("%d", &T);
while (T--)
{
printf("Case #%d: ", cas++);
run();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: