中文题目:
官方解题:
这个题目上来可能会让人觉得有点束手无策, 但是实际上这道题很简单, 题目允许的范围是75到80分钟, 而歌曲实际上范围还是很大的. 我们只要确定每位歌手只选择两首歌曲即可.
这道题, 我们可以将歌曲首先按照长度由长到短的顺序进行排列, 这样我们首先选择那些长的歌曲, 再选择短的歌曲来保证最后的播放列表能够满足75到80分钟的要求. 换句话说, 我们首先用较大的石头去填坑, 再用小石头把坑填好. 思路已经有了, 接下来我们需要实现代码:
$songs = Get-Content songlist.csv |`
% { $song = $_.Split(',');
$hash = New-Object -TypeName HashTable
$hash.artist = $song[0];
$hash.name = $song[1];
$hash.time = [TimeSpan] "00:$($song[2])";
$hash
}
$songs = $songs | Sort-Object -Property @{e = {$_.time};d=$true}
$atimes = @{}
$low = New-TimeSpan -Minute 75
$high = New-TimeSpan -Minute 80
$total = New-TimeSpan
$cd = $(foreach ($song in $songs)
{
if (($total -ge $low) -and ($total -le $high)) { break }
if ($atimes[$song.artist] -lt 2)
{
if (($total -lt $low) -and (($total + $song.time) -le $high))
{
$total = $total + $song.time;
$atimes[$song.artist]++;
$song
}
}
}) | Sort-Object -Property @{e={$_.artist}} |`
Select-Object -Property @{n="artist";e={$_.artist}},@{n="name";e={$_.name}},@{n="time";e={$_.time}}
$cd | %{ $_.artist + "`t" + $_.name + "`t" + "$($_.time.Minutes + $_.time.Hours * 60):$('{0:D2}' -f $_.time.Seconds)" }
""
"Total music time: $($total.Minutes + $total.Hours * 60):$('{0:D2}' -f $total.Seconds)"
每首歌曲被封装在hashtable对象中, 每首歌曲都用一个hashtable表示. 歌曲的长度用TimeSpan来表示, 因为TimeSpan已经完成了很多时间的计算, 我们完全可以不用考虑这些琐碎的细节.
接下来用Sort-Object对时间进行倒序, 因为使用TimeSpan, 所有PowerShell能够利用该对象完成比较, 我们不需要进行干涉. 每个歌手最多只能选择两首歌曲, 那么建立hash表进行记录是再好不过的决定. 对所有歌曲进行迭代, 如果歌曲加入后, 能够让结果趋向75到80分钟, 并且该名歌手还没有选满2首, 那么将改歌曲输出. 我们还需要主要进行排序工作和时间的统计.
阅读(1235) | 评论(0) | 转发(0) |