Hdu--5045(状态压缩DP)
2014-09-28 01:40:20
思路:根据题目的意思,考虑到:只有所有的人的编程时间达到某个值(如k)后才能有一个人的编程时间达到k+1,所以就是对于每n个连续问题的人员指派是1,2...n的一种排列。
考虑到人数少,直接状压,用dp[i][j]来表示考虑第 i 个问题时,状态为 j 时的最优解,j 是一个二进制数,它的第 p 位为0说明第 p+1 个人当前还没被指派做题。(若发现 j 的0 - N-1位都为零,则全置为0,开始考虑下一段n个连续问题)
题外话:当然,用n个人去匹配每n个连续问题也可用最优匹配来做,直接上模板。
1 /************************************************************************* 2 > File Name: 5045.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 28 Sep 2014 01:14:37 AM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <queue> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 #define lpos (pos << 1) 18 #define rpos (pos << 1|1) 19 #define getmid(l,r) (l + (r - l) / 2) 20 typedef long long ll; 21 const int INF = 1 << 29; 22 23 int T,N,M; 24 double p[15][1005]; 25 double dp[1005][1050]; 26 27 int main(){ 28 scanf("%d",&T); 29 for(int t = 1; t <= T; ++t){ 30 scanf("%d%d",&N,&M); 31 memset(dp,0,sizeof(dp)); 32 for(int i = 0; i < N; ++i){ 33 for(int j = 0; j < M; ++j) 34 scanf("%lf",&p[i][j]); 35 dp[0][1 << i] = p[i][0]; 36 } 37 int top = 1 << N,next; 38 for(int i = 1; i < M; ++i){ 39 for(int j = 0; j < top; ++j) if(dp[i - 1][j]){ 40 for(int k = 0; k < N; ++k) if(!(j & (1 << k))){ 41 next = j | (1 << k); 42 if(next == top - 1) next = 0; 43 if(dp[i - 1][j] + p[k][i] > dp[i][next]) 44 dp[i][next] = dp[i - 1][j] + p[k][i]; 45 } 46 } 47 } 48 double ans = 0.0; 49 for(int j = 0; j < top; ++j) 50 ans = max(ans,dp[M - 1][j]); 51 printf("Case #%d: %.5lf\n",t,ans); 52 } 53 return 0; 54 }