题目描述
在一个夜黑风高,下着暴风雨的夜晚,Farmer John的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚没有住满。 牛棚一个紧挨着另一个被排成一行,牛就住在里面过夜。 有些牛棚里有牛,有些没有。 所有的牛棚有相同的宽度。 自门遗失以后,farmer John必须尽快在牛棚之前竖立起新的木板。 他的新木材供应商将会供应他任何他想要的长度,但是吝啬的供应商只能提供有限数目的木板。 Farmer John想将他购买的木板总长度减到最少。
给出:可能买到的木板最大的数目M(1<= M<=50);牛棚的总数S(1<= S<=200); 牛棚里牛的总数C(1 <= C <=S);和牛所在的牛棚的编号stall_number(1 <= stall_number <= S),计算拦住所有有牛的牛棚所需木板的最小总长度。 输出所需木板的最小总长度作为答案。
样例输入&输出
sample input
4 50 18 3 4 6 8 14 15 16 17 21 25 26 27 30 31 40 41 42 43
sample output
25
分析&反思
一道贪心非常简单的题,用动归做,小错不断。
分析:
d [ i ][ j ] 表示第头牛到第j头牛之间的距离。
f [ i ][ j ] 表示第j头牛之前用i块木板所需要的木板长度。
状态转移方程:f [ i ][ j ] = f[ i-1 ][ k-1 ] + d[ k ][ j ] ( 1(可以是i) <= k <= j )
即第k头牛和第j头牛之间连上木板,加上第k-1头牛之前的用i-1块木板的最优情况。
反思:
1. 牛棚是一个块不是一个点,本身有一个单位的长度 (实际考虑也非常合理)。
2. 给出的牛棚编号不一定是升序,像动归或其他需要排序的题目,看好数据是不是按顺序给。
3. 动归好久没做了,起点数据的初始化赋值要注意,该inf的inf,该-1的-1,该。。。。。。
4.虽说用的模板越多越好,但10头牛也用不了50块木板啊,不要想当然的以为木板数小于牛棚数。
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf = 1000000000;
int b[202], d[202][202], f[52][202];
int m, s, c;
int main () {
freopen("barn1.in", "r", stdin);
freopen("barn1.out", "w", stdout);
cin >> m >> s >> c;
m = min(m, c);
for(int i = 1; i <= c; i++) cin >> b[i];
sort(b+1, b+c+1);
for(int i = 0; i <= 50; i++)
for(int j = 0; j <= 200; j++) f[i][j] = inf;
for(int i = 1; i <= c; i++)
for(int j = 1; j <= c; j++) d[i][j] = b[j] - b[i] + 1;
for(int i = 1; i <= c; i++) f[1][i] = b[i] - b[1] + 1;
int ans = inf;
for(int i = 2; i <= m; i++)
for(int j = 1; j <= c; j++)
for(int k = 1; k <= j; k++)
f[i][j] = min(f[i][j], f[i-1][k-1] + d[k][j]);
cout << f[m][c] << endl;
return 0;
}
备注
回归编程不久,有些问题是遗忘,有些问题是不熟练,有些问题没搞懂过。。。
希望每天都能保持热情 。