程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu5045(dp + 狀態壓縮)

hdu5045(dp + 狀態壓縮)

編輯:C++入門知識

hdu5045(dp + 狀態壓縮)


題意:

給出n個人,m道題;每道題只能一個人做;現在給出n行m列.是每個人做每一道題的成功率;

你現在要選出哪些人做哪些題,使成功率和最大.但是有一個條件做到任意一題時,做最多的人只能比做最少的人多做一道;

就是如果10個人,那麼前10題必須一人一題;


思路:

因為限制條件,所以前n道題,必須分給n個人一人一道,那麼每人只能做一次;

那麼用狀態壓縮表示哪些人做過了;

比如5個人00110;那麼下一道題就可以選擇剩下的3個人做,並且比較出一個最優的選擇;

當狀態變成11111時,就要重新置零;

所以用一個dp[i][j]表示前i道題,已經做的人的狀態是j;


AC:


#include
#include
#include
using namespace std;

double p[15][1005];
double dp[1005][1 << 10];
int n,m;
double solve() {
	for(int i = 0; i <= m; i++) {
		for(int j = 0 ; j < (1 << n); j++) {
			dp[i][j] = -1.0;
		}
	}
	dp[0][0] = 0;
	for(int i = 0; i < m; i++) {
		for(int k = 0; k < (1 << n); k++) {
			if(dp[i][k] < 0)
				continue;
			int s;
			for(int j = 0; j < n; j++) {
				int tmp = 1 << j;
				if(k & tmp) continue;
				s = k | tmp;
				if(s == (1 << n) - 1)
					s = 0;
				dp[i + 1][s] = max(dp[i + 1][s], dp[i][k] + p[j][i]);
			}
		}
	}
	double ans = 0.0;
	for(int i = 0; i < (1 << n); i++) {
		ans = max(ans, dp[m][i]);
	}
	return ans;
}
int main() {
	int t;
	int cas = 1;
	scanf("%d",&t);
	while(t--) {
		scanf("%d%d",&n,&m);
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < m; j++) {
				scanf("%lf",&p[i][j]);
			}
		}
		printf("Case #%d: %.5lf\n",cas++, solve());
	}
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved