题目,lintcode和leetcode都提供
https://www.lintcode.com/problem/1574
https://leetcode.cn/problems/number-of-music-playlists/description/
思路
本题对于新手来说其实非常难的,直接看答案吧,
本答案只给了记忆化搜索是版本,其实也是dp
答案
public class Solution {
/**
* @param n: the number of on his mobile phone
* @param m: in the middle of two songs, there are at least m other songs
* @param p: the number of songs he can listen to
* @return: the number of playlists
*/
public int getAns(int n, int m, int p) {
//同一道题:力扣920
//题解https://leetcode.cn/problems/number-of-music-playlists/solutions/1488748/by-carl-peng-23-4bck/
//题意不明确导致WA了几次。。。题目意思是说两首相同歌之间必须至少间隔K首歌,这里交代不明确。
return f(n,p,m);
}
public static int f(int n,int goal,int k){
int[][] dp = new int[105][105];
for (int[] ints : dp) {
Arrays.fill(ints,-1);
}
return dfs(0,0,n,goal,k,dp);
}
//前面已经选了j种歌曲,现在要选第i首歌,n,goal,k是固定参数
public static int dfs(int i,int j,int n,int goal,int k,int[][] dp){
//此时已经到最后一首歌,还想继续往下选择一首歌
if(i==goal){
//每首歌至少播放一次
if(j<n) return 0;
return 1;
}
if(dp[i][j]!=-1) return dp[i][j];
long ans =0;
//假设i是一首新歌,已经选了j种歌,那么还有n-j种歌可以选
if(j<n){ //保证n-j大于0
ans+=(long)dfs(i+1,j+1,n,goal,k,dp)*(n-j);
}
//假设i是一首旧歌,直接从j种歌曲里面选一首
if(j>k) //保证再次播放的时候里面有k首其他的歌
ans+=(long)dfs(i+1,j,n,goal,k,dp)*(j-k);
dp[i][j] = (int)(ans%1000000007);
return dp[i][j];
}
}