【好题】dp+排序+贪心——SEERC 2019

/*
首先考虑dp状态:dp[i][j][k]表示考虑了前i个任务,凑成的第一级经验是j,第二级经验是k的用时
由于一级完成任务溢出的经验会给二级,所以任务完成顺序是对结果有影响的:
    3 10 2
    5 3 4 2
    5 4 3 3
    2 5 1 4
    这组数据,如果先完成任务一或任务二,那么最终是完不成升两级的 
    那么对于一级完成的任务而言,经验越多的任务放在越后面就越好
所以一开始要给任务以x进行升序排序     
*/
#include<bits/stdc++.h>
using namespace std;
#define N 1005
#define ll long long

const ll INF=0x3f3f3f3f3f3f3f3f;

struct Node {
    ll x,t,y,r;
}p[N];
ll n,s1,s2,dp[2][N][N];

int cmp(Node a,Node b){return a.x<b.x;}

int main(){
    cin>>n>>s1>>s2;
    for(int i=1;i<=n;i++)
        cin>>p[i].x>>p[i].t>>p[i].y>>p[i].r;
    memset(dp,0x3f,sizeof dp);
    dp[0][0][0]=0;
    
    sort(p+1,p+1+n,cmp);
    
    int cur=0;
    for(int i=1;i<=n;i++) {
        memcpy(dp[cur^1],dp[cur],sizeof dp[cur]);
        for(int j=0;j<=s1;j++)
            for(int k=0;k<=s2;k++)if(dp[cur][j][k]!=INF){
                //p[i]用在第一级上
                if(j<s1){
                    int nxt=j+p[i].x;
                    if(nxt<=s1)
                        dp[cur^1][nxt][k]=min(dp[cur^1][nxt][k],dp[cur][j][k]+p[i].t);
                    else {
                        int tmp=nxt-s1+k;if(tmp>s2)tmp=s2;
                        dp[cur^1][s1][tmp]=min(dp[cur^1][s1][tmp],dp[cur][j][k]+p[i].t);
                    } 
                }
                
                //p[i]用在第二级上
                int nxt=k+p[i].y;if(nxt>s2)nxt=s2;
                dp[cur^1][j][nxt]=min(dp[cur^1][j][nxt],dp[cur][j][k]+p[i].r); 
            }
            
        cur^=1;
    }
    
    if(dp[cur][s1][s2]==INF || dp[cur][s1][s2]==0)cout<<-1<<'\n';
    else cout<<dp[cur][s1][s2]<<"\n";
}
/*
2 3 4
3 3 1 1
4 1 4 1 
*/

 

posted on 2020-04-12 19:16  zsben  阅读(241)  评论(0编辑  收藏  举报

导航