P1064 [NOIP2006 提高组] 金明的预算方案

1.不选,然后去考虑下一个

2.选且只选这个主件

3.选这个主件,并且选附件1

4.选这个主件,并且选附件2

5.选这个主件,并且选附件1和附件2.

dfs havent work it out

wait to work

/*
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

2200
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------debug\n");
using namespace std;
const int maxn=32005;

int n,m;
int main_w[maxn],main_c[maxn],nxt_w[maxn][3],nxt_c[maxn][3];
int f[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int v,p,q;
        cin>>v>>p>>q;
        if(q==0)
        {
            main_w[i]=v;
            main_c[i]=p*v;
        }
        else
        {
            nxt_w[q][ ++nxt_w[q][0] ]=v;
            nxt_c[q][ nxt_w[q][0] ]=v*p;
        }
    }
    
    for(int i=1;i<=m;i++)
    {
        for(int j=n;main_w[i]!=0&&j>=main_w[i];j--)
        {
            f[j]=max(f[j],f[j-main_w[i]]+main_c[i]);
            
            if(j>=nxt_w[i][1]+main_w[i])   
            f[j]=max(f[j],f[ j-nxt_w[i][1]-main_w[i] ]+nxt_c[i][1]+main_c[i]);
            
            if(j>=nxt_w[i][2]+main_w[i]) 
            f[j]=max(f[j],f[ j-nxt_w[i][2]-main_w[i] ]+nxt_c[i][2]+main_c[i]);
            
            if(j>=nxt_w[i][1]+nxt_w[i][2]+main_w[i]) 
            f[j]=max(f[j],f[j-nxt_w[i][1]-nxt_w[i][2]-main_w[i] ]+nxt_c[i][1]+nxt_c[i][2]+main_c[i]);
        }
    }
    cout<<f[n]<<endl;
    return 0;
}

/*
#include<bits/stdc++.h>
using namespace std;

int N,m,w[200],c[200],x,dp[200][40000];//数组大小qwq
int head[200],k=1;//链式前向星加边用
struct edge
{
    int to,next;
}e[200];//树的边

void adde(int u,int v)//链式前向星加边
{
    e[k].to=v;
    e[k].next=head[u];
    head[u]=k++;
}

void dfs(int u,int t,int fa)
//u是当前节点,t是当前容量,fa是父亲节点
{
    if(t<=0)return;//装不下了
    for(int i=head[u];i;i=e[i].next)//访问与该点相连的每一条边
    {
        int v=e[i].to;
        if(v==fa)continue;//如果是父节点则跳过
        for(int k=N-w[v];k>=0;k--)
            dp[v][k]=dp[u][k]+c[v];//要选子树,就必须选该节点
        dfs(v,t-w[v],u);//继续递归
        for(int k=N;k>=w[v];k--)
            dp[u][k]=max(dp[u][k],dp[v][k-w[v]]);//选或不选(这是01背包)
    }
}

int main()
{
    scanf("%d%d",&N,&m);
    for(register int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&w[i],&c[i],&x);
        c[i]*=w[i];//读入
        adde(i,x);adde(x,i);//连双向边
    }
    dfs(0,N,-1);//0为虚拟根节点,深搜跑dp
    int ans=0;
    for(register int i=0;i<=N;i++)//这里一定要写<=,因为可以刚好把钱花完
        ans=max(ans,dp[0][i]);//统计答案
    printf("%d\n",ans);//输出
    return 0;//结束了罪恶的一生
}
*/
View Code
 

 

 
 
 
posted @ 2023-07-08 14:09  JMXZ  阅读(9)  评论(0)    收藏  举报