机器分配
说是泛化背包,其实很简单啦,就是找最小字典序路径很讨厌
不过 倒序做就不会有这个烦恼了
#include<bits/stdc++.h> #define re return #define inc(i,l,r) for(int i=l;i<=r;++i) #define dec(i,l,r) for(int i=l;i>=r;--i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n,m,ans[20][20],f[20][20],last[20][20],b[20],c[20],cnt; int a[20][20]; inline bool check(int i,int j,int k) { b[i]=f[i][j];c[i]=f[i][k]; if(i==1) { inc(i,1,cnt) if(b[i]<c[i])re 1; else if(b[i]>c[i])re 0; } check(i-1,last[i][j],last[i][k]); } inline void dfs(int i,int j) { if(!i)re ; dfs(i-1,last[i][j]); printf("%d %d\n",i,f[i][j]); } int main() { rd(n),rd(m); inc(i,1,n)inc(j,1,m) rd(a[i][j]); inc(j,1,m)ans[1][j]=a[1][j],f[1][j]=j; inc(i,2,n) { cnt=i-1; inc(j,1,m)//前i家店共选了j个机器 { ans[i][j]=ans[i-1][j]; last[i][j]=j;//前i-1家店选了j个机器 inc(k,1,j)//第i家店选k个机器 { if(ans[i][j]<ans[i-1][j-k]+a[i][k]) { ans[i][j]=ans[i-1][j-k]+a[i][k]; f[i][j]=k; last[i][j]=j-k; } else if(ans[i][j]==ans[i-1][j-k]+a[i][k]) { if(check(i-1,last[i][j],j-k))continue; f[i][j]=k; last[i][j]=j-k; } } } } printf("%d\n",ans[n][m]); dfs(n,m); re 0; }