POJ 3265 Problem Solving

题意:P个问题,雇佣相同的人去解决,每个人每月解决一道题,每个人解决问题的代价都分两次,解决问题当月给a[i],事后第二月给b[i],然后每个月有m的钱,问最快多久解决所有问题。(问题必须按照序号一个个解决)

题解:dp[i][j][k]代表第i个月解决完前j件事还剩k元钱所需要在下一个月支付的最小价格,由于空间比较大,所以用交叉dp的方法去更新。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int P=305,M=1005,inf=0x3f3f3f3f;
int dp[2][P][M];
int a[P],b[P];
int main()
{
    int m,p,ans=inf,x,y;
    scanf("%d%d",&m,&p);
    for(int i=1;i<=p;i++)
        scanf("%d%d",&a[i],&b[i]);
    memset(dp,0x3f,sizeof(dp));
    dp[1][0][0]=0;
    x=0,y=1;
    for(int i=1;;i++)
    {
        x=i&1;
        y=x^1;
        memset(dp[y],0x3f,sizeof(dp[y]));
        for(int j=0;j<=p;j++)
        {
            for(int k=0;k<=m;k++)
            {
                if(dp[x][j][k]!=inf)
                {
                    if(j==p)
                        ans=min(ans,(dp[x][j][k]==0)?i:(i+1));
                    else if(k>=a[j+1]&&dp[x][j][k]+b[j+1]<=m)
                        dp[x][j+1][k-a[j+1]]=min(dp[x][j+1][k-a[j+1]],dp[x][j][k]+b[j+1]);
                    dp[y][j][m-dp[x][j][k]]=0;
                }
            }
        }
        if(ans!=inf)
            break;
    }
    printf("%d\n",ans);
    return 0;
}


你可能感兴趣的:(POJ 3265 Problem Solving)