机器分配(AcWing)

题目描述

机器分配(AcWing)_第1张图片

 题目链接:

https://www.acwing.com/problem/content/description/1015/

 思路:

 本题不是难题,但是还蛮有意思,我就简单写一下博客,总结一下,也算是对自己的提醒

(解法一): 暴力DFS搜索, 复杂度: C_{n+m-1}^{n-1}. 就是对每一个公司,暴力枚举其所有可能的方案,然后统计最大值。 这种做法没什么可以说的。

解法一的代码:

#include
#include
#include
#include
using namespace std;
const int N=16;
int a[N][N];
int n,m;
int ans=0;
int b[N];
int jie[N];
void dfs(int value,int cur,int sum){
	if(sum>m) return ;
	if(cur==n){
		
		int res=value+a[n][m-sum];
		b[n]=m-sum;
		if(res>ans){
			ans=res;
			for(int i=1;i<=n;i++){
				jie[i]=b[i];
			}
			return ;
		}
		return ;
	}
	for(int i=0;sum+i<=m;i++){
		b[cur]=i;
		int now_value=value+a[cur][i];
		dfs(now_value,cur+1,sum+i);
	}
	
	return ;
}


int main(void){
	
	scanf("%d%d",&n,&m);	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
		}
	}
	dfs(0,1,0);
	printf("%d\n",ans);
	for(int i=1;i<=n;i++){
		printf("%d %d\n",i,jie[i]);
	}
	return 0;
}

(解法二): DP, 背包问题求方案,时间复杂度O(nm2)

用f[i][j]表示1~i 这些公司,且总共分配了j个机器的最大价值。则,不难得到状态转移:

f[i][j]=max(f[i-1][j-k]), k=0,1,...j.

最终答案: f[n][m].

此外,本题还要求我们输出最优的方案,因此需要在dp更新的时候同时记录一下是如何更新的。

pre[i][j] 表示1~i 这些公司,总共分配了j个机器时的最优决策在第i个公司处分配了多少个机器

那么就可以递归地找到最优解了

解法二的代码:

#include
#include
#include
using namespace std;
const int N=16;
const int inf=-0x3f3f3f3f;
int f[N][N];
int pre[N][N];
int a[N][N];
int n,m;
int jie[N];

int main(void){
	
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&a[i][j]);
		}
	}
	memset(f,-0x3f,sizeof(f));
	f[0][0]=0;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			for(int k=0;k<=j;k++){
				if(f[i-1][j-k]==inf) continue;
				int res=f[i-1][j-k]+a[i][k];
				if(res>f[i][j]){
					f[i][j]=res;
					pre[i][j]=k;
				}
			}
		}
	}
	int ans=f[n][m];
	printf("%d\n",ans);
	int now_volumn=m;
	for(int i=n;i>=1;i--){
		int k=pre[i][now_volumn];
		now_volumn-=k;
		jie[i]=k;
	}
	for(int i=1;i<=n;i++){
		printf("%d %d\n",i,jie[i]);
	}
	return 0;
}

你可能感兴趣的:(算法题,算法,数据结构,动态规划)