记录编号 320285 评测结果 AAAAAA
题目名称 [NOI 1998]免费馅饼 最终得分 100
用户昵称 GravatarGo灬Fire 是否通过 通过
代码语言 C++ 运行时间 0.017 s
提交时间 2016-10-11 20:32:20 内存使用 11.99 MiB
显示代码纯文本
/*
	Name: 免费馅饼 
	Copyright: 
	Author: Go灬Fire 
	Date: 11/10/16 20:25
	Description: c[i][j]代表时间为i时在j处馅饼的价值,f[i][j]代表时间为i时在j处已获得的最优的解
				首先要处理根本不可能接到的馅饼,去掉
				Dp是s数组要记录它是从哪一个状态转移
				递归输出 
				特判:舞台宽度为1,站着不动吃馅饼 
*/
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#define Begin freopen("freepizza.in","r",stdin);freopen("freepizza.out","w",stdout);
#define End fclose(stdin);fclose(stdout);
using namespace std;
const int maxn=1010;
int w,h,f[maxn][maxn],c[maxn][maxn],s[maxn][maxn];
void Init();
void Print(int t,int w){
	if(t<=0 || w<=0) return;
	Print(t-1,w+s[t][w]);
	printf("%d\n",-s[t][w]);
}
int _max(int a,int b,int c,int d,int e){
	a=max(a,b);c=max(c,d);c=max(c,e);
	return max(a,c);
}
int main(){
    Begin;
    Init();
    //system("pause");
    End;
	return 0;
}
void Init(){
	//f[i][j]与c[i][j]第一维是时间,第二维是空间 
	scanf("%d%d",&w,&h);
	int time=0,end=0,x,sp,val;
	while(scanf("%d%d%d%d",&time,&x,&sp,&val)!=EOF){
		if((h-1)%sp!=0)continue;//根本不可能接到的馅饼
		c[time+(h-1)/sp][x]+=val;
		end=max(end,time+(h-1)/sp); 
	}
	if(w==1){
		int ans=0;
		for(int i=1;i<=end;i++)ans+=c[i][1];
		if(h==1)ans=100,end=1; 
		printf("%d\n",ans);
		for(int i=1;i<=end;i++)puts("0");
		return;
	}
	memset(f,-1,sizeof(f));//这样可以保证字典序最小,我也不太清楚 
	f[0][(1+w)>>1]=c[0][(1+w)>>1];//初值 
	int set=0,ans=0;
	for(int i=1;i<=end;i++){//枚举时间 
		for(int j=1;j<=w;j++){//枚举空间 
			int k=j-2;if(k<0)k=0;
			f[i][j]=_max(f[i-1][j-1],f[i-1][k],f[i-1][j],f[i-1][j+1],f[i-1][j+2])+c[i][j];
			if(i==end && ans<f[i][j]){
				ans=f[i][j];set=j;
			}
			if(f[i][j]==f[i-1][j+2]+c[i][j])s[i][j]=2;
			if(f[i][j]==f[i-1][j+1]+c[i][j])s[i][j]=1;
			if(f[i][j]==f[i-1][j]+c[i][j])s[i][j]=0;
			if(f[i][j]==f[i-1][j-1]+c[i][j])s[i][j]=-1;
			if(f[i][j]==f[i-1][k]+c[i][j])s[i][j]=-2;
			
		}
	}
	printf("%d\n",ans);
	//printf("%d %d\n",end,set);
	Print(end,set);
}