[jzoj 4224] 食物 {多重揹包}

題目

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述


解題思路

很容易看出題面給出的是讓我們求一遍01揹包和完全揹包。
但是這肯定會超時:
那麼對於01揹包,我們用二進制優化
對於完全揹包,我們講完全揹包的方程的狀態與答案換一下,因爲花費最多50000


代碼二進制優化01揹包+完全揹包

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fre(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
#define M 210
#define N 110
using namespace std;
int n,m,a[M][N][N],f[M][N],flag;
int main(){
// fre(lines); 
	scanf("%d%d",&n,&m); 
	memset(f,125/3,sizeof(f)); flag=f[m][n]; 
	memset(a,125/3,sizeof(a)); 
	for (int i=1;i<=n;i++)
	 for (int j=1;j<=n;j++) if (i!=j){
	 	int t,x[21]; 
	 	scanf("%d",&t); 
	 	for (int q=1;q<=t;q++) {
			 scanf("%d",&x[q]); 
	 		 if (!x[q]) x[q]=flag; 
		 }
	 	for (int q=1;q<=m;q++) a[q][i][j]=x[(q-1)%t+1]; 
	 }
	 f[0][1]=0; 
	 for (int k=1;k<=m;k++) if (k!=m){
	  for (int j=1;j<=n;j++) 
	   for (int i=1;i<=n;i++)
	   if (j!=i) f[k][j]=min(f[k][j],f[k-1][i]+a[k][i][j]); 
	 } else {
	   int j=n; 
	   for (int i=1;i<=n;i++)
	   if (j!=i) f[k][j]=min(f[k][j],f[k-1][i]+a[k][i][j]); 
	 }
	printf("%d",f[m][n]!=flag?f[m][n]:0); 
}