272. [NOI1998] 免費餡餅
★☆ 輸入文件:freepizza.in
輸出文件:freepizza.out
簡單對比時間限制:1 s 內存限制:128 MB
SERKOI最新推出了一種叫做“免費餡餅”的遊戲:遊戲在一個舞臺上進行。舞臺的寬度爲W格,天幕的高度爲H格,遊戲者佔一格。開始時遊戲者站在舞臺的正中央,手裏拿着一個托盤。下圖爲天幕的高度爲4格時某一個時刻遊戲者接餡餅的情景。
遊戲開始後,從舞臺天幕頂端的格子中不斷出現餡餅並垂直下落。遊戲者左右移動去接餡餅。遊戲者每秒可以向左或向右移動一格或兩格,也可以站在原地不動。
餡餅有很多種,遊戲者事先根據自己的口味,對各種餡餅依次打了分。同時,在8-308電腦的遙控下,各種餡餅下落的速度也是不一樣的,下落速度以格/秒爲單位。
當餡餅在某一秒末恰好到達遊戲者所在的格子中,遊戲者就收集到了這塊餡餅。
寫一個程序,幫助我們的遊戲者收集餡餅,使得所收集餡餅的分數之和最大。
輸入
輸入文件的第一行是用空格隔開的兩個正整數,分別給出了舞臺的寬度W(1到99之間的奇數)和高度H(1到100之間的整數)。
接下來依餡餅的初始下落時間順序給出了所有餡餅的信息。每一行給出了一塊餡餅的信息。由四個正整數組成,分別表示了餡餅的初始下落時刻(0到1000秒),水平位置、下落速度(1到100)以及分值。遊戲開始時刻爲0。從1開始自左向右依次對水平方向的每格編號。
輸入文件中同一行相鄰兩項之間用一個或多個空格隔開。
輸出
輸出文件的第一行給出了一個正整數,表示你的程序所收集的最大分數之和。
其後的每一行依時間順序給出了遊戲者每秒的決策。輸出0表示原地不動、1或2表示向右移動一步或兩步、-1 或-2表示向左移動一步或兩步。輸出應持續到遊戲者收集完他要收集的最後一塊餡餅爲止。
樣例輸入
3 3 0 1 2 5 0 2 1 3 1 2 1 3 1 3 1 4
樣例輸出
12 -1 1 1
注意只有恰好某個時間餡餅在最底層才能接住
#include <iostream>
#include <cstdio>
using namespace std;
#define INF 9999999
int w,h;
int dp[1001][101];
int sel[1001][101];
int mat[1001][101];
void PrintAns(int Floor,int Pos);
int main()
{
freopen("freepizza.in","r",stdin);
freopen("freepizza.out","w",stdout);
scanf("%d%d",&w,&h);
int cnt=0;
int s,pos,v,grade;
int lasts;
lasts=0;
while(scanf("%d%d%d%d",&s,&pos,&v,&grade)==4)
{
if((h-1)%v==0 || s==0)
{
mat[s+(h-1)/v][pos]+=grade;
lasts=max(lasts,s+(h-1)/v);
cnt++;
}
}
if(!cnt)
{
printf("0\n");
return 0;
}
for(int i=1;i<=w;i++)
dp[0][i]=-INF;
dp[0][w/2+1]=mat[0][w/2+1];
for(int i=1;i<=lasts;i++)
{
for(int j=1;j<=w;j++)
{
int maxx=-INF;
if(j>=3)
{
if(maxx<dp[i-1][j-2])
{
maxx=dp[i-1][j-2];
sel[i][j]=2;
}
}
if(j>=2)
{
if(maxx<dp[i-1][j-1])
{
maxx=dp[i-1][j-1];
sel[i][j]=1;
}
}
if(maxx<dp[i-1][j])
{
maxx=dp[i-1][j];
sel[i][j]=0;
}
if(j<=w-1)
{
if(maxx<dp[i-1][j+1])
{
maxx=dp[i-1][j+1];
sel[i][j]=-1;
}
}
if(j<=w-2)
{
if(maxx<dp[i-1][j+2])
{
maxx=dp[i-1][j+2];
sel[i][j]=-2;
}
}
dp[i][j]=maxx+mat[i][j];
}
}
int maxi;
int maxx=-INF;
for(int i=1;i<=w;i++)
{
if(maxx<dp[lasts][i])
{
maxx=dp[lasts][i];
maxi=i;
}
}
printf("%d\n",maxx);
PrintAns(lasts,maxi);
if(lasts==0) printf("0\n");
return 0;
}
void PrintAns(int Floor,int Pos)
{
if(Floor<1) return;
PrintAns(Floor-1,Pos-sel[Floor][Pos]);
printf("%d\n",sel[Floor][Pos]);
}