题目:https://loj.ac/problem/2557
第一个点可以暴搜。
第三个点无依赖关系,k=3,可以 DP 。dp[ cr ][ i ][ j ] 表示前 cr 个任务、第一台机器最晚完成时间是 i 、第二台机器最晚完成时间是 j ,第三台机器最晚完成时间是多少。数组开 500 就行了。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int Mx(int a,int b){return a>b?a:b;} int Mn(int a,int b){return a<b?a:b;} const int N=55,M=505,K=5,INF=1e9+5; int n,m,k,op,dp[N][M][M],pr[N][M][M][2]; int t[N][K],r[K][K],prn[N]; int main() { scanf("%d%d%d%d",&n,&m,&k,&op); for(int i=1;i<=n;i++) for(int j=1;j<=k;j++) scanf("%d",&t[i][j]); for(int i=1;i<=k;i++) for(int j=1;j<=k;j++) scanf("%d",&r[i][j]); memset(dp,0x3f,sizeof dp); dp[0][0][0]=0; for(int cr=1;cr<=n;cr++) for(int i=0;i<=500;i++) for(int j=0;j<=500;j++) { int w=t[cr][3]; dp[cr][i][j]=dp[cr-1][i][j]+w; pr[cr][i][j][0]=i; pr[cr][i][j][1]=j; w=t[cr][1]; if(i>=w&&dp[cr-1][i-w][j]<dp[cr][i][j]) { dp[cr][i][j]=dp[cr-1][i-w][j]; pr[cr][i][j][0]=i-w; pr[cr][i][j][1]=j; } w=t[cr][2]; if(j>=w&&dp[cr-1][i][j-w]<dp[cr][i][j]) { dp[cr][i][j]=dp[cr-1][i][j-w]; pr[cr][i][j][0]=i; pr[cr][i][j][1]=j-w; } } int ans=INF,r0,r1; for(int i=0;i<=500;i++) for(int j=0;j<=500;j++) { int d=Mx(Mx(i,j),dp[n][i][j]); if(d<ans)ans=d,r0=i,r1=j; } for(int i=n;i;i--) { int t0=pr[i][r0][r1][0],t1=pr[i][r0][r1][1]; if(t0!=r0)prn[i]=1; else if(t1!=r1)prn[i]=2; else prn[i]=3; r0=t0; r1=t1; } for(int i=1;i<=n;i++)printf("%d ",prn[i]);puts(""); return 0; }