51nod1636-基础dp&打表-教育改革

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1636
中文题意,不在赘述。
首先写的一个回溯,被一组数据卡了。(应该是这一组非法状态太多)
考虑到每门科目的作业区间很小。用动态规划搞之。
dp[i][j][k] 为1-i天,末尾为j课程,选择的作业数目为k(考虑到太大,用和左边界的差值表示)
原题中还有x和y记录课程号和作业数,用来递归输出。
wa了几点。如果非法状态用0表示,那么最后的ans也应该是0。不然就不会输出no。
用long long
附 回溯代码(也调了好久qwq)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100;
ll dp[maxn][maxn][maxn];
int m,n;ll k;
struct Node{
      ll l,r,lim;
}node[maxn];
bool cmp2(Node a,Node b){
    return a.lim<b.lim;
}
int main()
{   while(~scanf("%d%d%lld",&m,&n,&k)){
          for(int i=0;i<n;i++){
              scanf("%lld%lld%lld",&node[i].l,&node[i].r,&node[i].lim);
          }
          memset(dp,-1,sizeof(dp));
          sort(node,node+n,cmp2);
          for(int i=0;i<n;i++){
              for(ll  j=node[i].l;j<=node[i].r;j++)
                  dp[1][i][j-node[i].l]=1ll*j;
          }
          for(int i=1;i<=m;i++){
              for(int j=i-1;j<n;j++){
                   for(ll x=node[j].l;x<=node[j].r;x++){
                       if(dp[i][j][x-node[j].l]==-1)
                          continue;
                        for(int jj=j+1;jj<n;jj++){
                             if(node[jj].lim<=node[j].lim) continue;
                             if(x*k>=node[jj].l&&x*k<=node[jj].r){
                                if(dp[i+1][jj][x*k-node[jj].l]<(x*k+dp[i][j][x-node[j].l])){
                                     dp[i+1][jj][x*k-node[jj].l]=x*k+dp[i][j][x-node[j].l];
                                }
                             }
                             if(1ll*(x+k)>=node[jj].l&&1ll*(x+k)<=node[jj].r){
                                if(dp[i+1][jj][x+k-node[jj].l]<(x+k+dp[i][j][x-node[j].l])){
                                     dp[i+1][jj][x+k-node[jj].l]=1ll*(x+k+dp[i][j][x-node[j].l]);
                                }
                             }
                        }
                   }
              }
          }
          ll ans=-1;
          for(int i=0;i<n;i++){
             for(ll j=node[i].l;j<=node[i].r;j++){
                 ans=max(ans,dp[m][i][j-node[i].l]);
             }
          }
          if(ans!=-1){
          puts("YES");
          printf("%lld\n",ans);
          }
          else
            puts("NO");
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
/*回溯,就t一组。
*/
const int maxn=1e5;
typedef long long ll;
const ll inf=1e17;
struct Node{
    ll l,r;
    ll dif;
}node[maxn];
bool cmp2(Node a,Node b){
    return a.dif<b.dif;
}
ll lim;
int m,n;
ll ans;
bool vis[maxn];
int siz;
void dfs(int x,ll s,ll chi){
     if(siz==m){
        ans=max(ans,s);
        return ;
     }
     for(int i=x;i<n;i++){
         if(!vis[i]&&node[i].dif>node[x].dif){
            if(max(chi*lim,chi+lim)>=node[i].l&&max(chi*lim,chi+lim)<=node[i].r){
                //s+=max(chi*lim,chi+lim);
                //cout<<x<<"fir"<<i<<" "<<siz<<endl;
                vis[i]=true;
                siz++;
                dfs(i,s+max(chi*lim,chi+lim),max(chi*lim,chi+lim));
                vis[i]=false;
                siz--;
             }
              if(min(chi*lim,chi+lim)>=node[i].l&&min(chi*lim,chi+lim)<=node[i].r){
                siz++;
                vis[i]=true;
                dfs(i,s+min(chi*lim,chi+lim),min(chi*lim,chi+lim));
                vis[i]=false;
                siz--;
             }
                    //vis[i]=false;
                  //dfs(i+1,s,chi);
         }
     }

}
int main()
{   int t;
    while(~scanf("%d%d%lld",&m,&n,&lim)){
          for(int i=0;i<n;i++){
              scanf("%lld%lld%lld",&node[i].l,&node[i].r,&node[i].dif);
          }
          sort(node,node+n,cmp2);
          ans=-1;
          //cout<<"??"<<endl;
          /*for(int i=0;i<n;i++)
             for(ll j=node[i].l;j<=node[i].r;j++){
                   memset(vis,false,sizeof(vis));                   siz=0;
                   siz=1;
                   vis[i]=true;
                   //cout<<i<<" "<<j<<endl;*/
                   for(int i=0;i<n;i++)
                   for(ll j=node[i].l;j<=node[i].r;j++){
                     memset(vis,false,sizeof(vis));
                     siz=1;
                     dfs(i,j,j);
                     }

                  // }

           if(ans!=-1){
                  puts("YES");
                  printf("%lld\n",ans);
           }
           else
               puts("NO");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值