DP,注意单组输入,题目的进程无后效性,适合DP,
由于当时没有估计出车子数量,用了滚动数组。
现在来谈下DP状态的表示,
比较容易想到的是DP【i】【j】【k】(现在的车子编号,队列1长度,队列2长度)
明显MLE,其实我们只需要有前两维即可,因为最后一维可以从前面两维推知:k=sum【i】-j;
问题转为存在性问题了,dp【i】【j】=dp【i-1】【j】|dp【i-1】【j-len【i】】(分别为放在队列1,放在队列2)
注意细节处理
详情见代码:
#include<stdio.h>
#include<string.h>
const int maxn=10007;
bool dp[2][maxn];//表示第i辆车时,第一个队列装了J的容量
int pre[501][maxn];
int sum[501];
int q[501];
void output(int ,int );
int main()
{
int max,i,j,a,ans,nn,c,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&max);
nn=1,ans=0,c=0;
max*=100;
memset(sum,0,sizeof(sum));
while(scanf("%d",&a)&&a)
q[nn++]=a;
sum[1]=q[1];
for(i=2;i<nn;i++)
sum[i]+=sum[i-1]+q[i];
memset(dp,false,sizeof(dp));
memset(pre,-1,sizeof(pre));
dp[0][0]=true;
for(i=1;i<nn;i++)
{
memset(dp[i&1],false,sizeof(dp[i&1]));
for(j=max;j>=0;j--)//第一个队列的长度
{
if(sum[i-1]-j>max)//第二个队列爆了
break;
if(sum[i]-j<=max)//第二个队列还能装得下
{
if(j-q[i]>=0)
dp[i&1][j]=dp[(i-1)&1][j]|dp[(i-1)&1][j-q[i]];
else dp[i&1][j]=dp[(i-1)&1][j];
if(dp[(i-1)&1][j])
pre[i][j]=0;//表示装在第二个队列
else if(j-q[i]>=0&&dp[(i-1)&1][j-q[i]])
pre[i][j]=1;
}
else if(j-q[i]>=0)
{
dp[i&1][j]=dp[(i-1)&1][j-q[i]];
pre[i][j]=1;
}
if(dp[i&1][j])
{
c=j;
ans=i;
}
}
if(ans!=i) //如果这一个车子无法被装下,break
break;
}
printf("%d\n",ans);
if(ans)
output(ans,c);
}
return 0;
}
void output(int x,int y)
{
if(x<=0) return ;
if(pre[x][y]==1)
{
output(x-1,y-q[x]);
printf("port\n");
}
else if(pre[x][y]==0)
{
output(x-1,y);
printf("starboard\n");
}
else if(pre[x][y]==-1)
{
while(1) puts("S");
}
}