5.26 模拟赛

5.26模拟赛

DP专题

A 货币系统

NOIP2018原题 完全背包裸题

码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<deque>
#include<set>
#include<stack>
#include<bitset>
#include<cstring>
#define ll long long
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
#define re register
using namespace std;
const int INF=0x3f3f3f3f,N=110,M=25010;

inline int read(){
	int x=0,y=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*y;
}

int t,n,a[N],f[M],maxx=0,ans=0;

int main(){

	// freopen("money.in","r",stdin);
	// freopen("money.ans","w",stdout);
	
	t=read();
	while(t--){
		n=read();
		ans=n;
		memset(f,-INF,sizeof f);
		maxx=0;
		for(int i=1;i<=n;i++) a[i]=read(),maxx=max(maxx,a[i]),f[a[i]]=1;
		sort(a+1,a+1+n);
		for(int i=1;i<=n;i++){
			for(int j=a[i];j<=maxx;j++){
				int o=f[j];
				f[j]=max(f[j],f[j-a[i]]+1);
				
			}
		}
		for(int i=1;i<=n;i++) if(f[a[i]]>1) ans--;
		printf("%d\n",ans);
	}
	
	
	// fclose(stdin);
	// fclose(stdout);

    return 0;
}


B happiness

不可做

题意:有两辆有体积的车,同时来回,有一些物品有体积,问最少走多少趟能把所有物品转移

听说可以用状压,但是我不会,等dalao来教,我只会二分答案用dfs判断(其实二不二分对复杂度也没啥影响,n太小了

码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<deque>
#include<set>
#include<stack>
#include<bitset>
#include<cstring>
#define ll long long
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
using namespace std;
const int INF=0x3f3f3f3f,N=110,S=1100;

int t;

inline int read(){
    int x=0,y=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*y;
}

namespace work{
    int n,c1,c2,a[N],c[2*N],flag=0;
    void clear(){
        n=0,c1=0,c2=0;
        flag=0;
        memset(a,0,sizeof a);
    }
    void readin(){
        n=read();
        int c,b;
        c=read();
        b=read();
        c1=min(c,b);
        c2=max(c,b);
        for(int i=1;i<=n;i++) cin>>a[i];
        sort(a+1,a+1+n);
    }

    void dfs(int x,int cnt){
        if(!x){flag=1;return;}
        for(int i=1;i<=cnt*2&&!flag;i++){
            if(c[i]>=a[x]) c[i]-=a[x],dfs(x-1,cnt),c[i]+=a[x];
        }
    }

    bool check(int i){
        flag=0;
        for(int j=1;j<=i;j++) c[j]=c1;
        for(int j=i+1;j<=2*i;j++) c[j]=c2;
        dfs(n,i);
        if(flag){
            return 1;
        }
        return 0;
    }

    void sswork(int k){
        int l=1,r=n;
        while(l<r){
            int mid=(l+r)>>1;
            if(check(mid)) r=mid;
            else l=mid+1;
        }
        printf("Scenario #%d:\n%d\n\n",k,l);
    }
    
}

int main(){

    t=read();
    int k=1;
    while(t--){
        work::clear();
        work::readin();
        work::sswork(k++);
    }
    
    return 0;
}

C 宝藏

题意:给个树,边有边权,点有点权,每次经过一条边贡献是\(-w\),第一次经过一个点贡献是\(val\),问从每个节点出发的最大贡献是多少

明显的换根DP,但是连根节点的DP都不会,考场上推柿子的时候考虑了三种情况,一种是从待更新的子树走到已更新的子树里,一种是从已更新的子树走到待更新的子树里,一种是只走待更新的子树,期望50,但是读取到20,考完了一想,只用记录从根节点走到待更新的子树里考虑回不回来就可以了,还简单,菜死了

抄的std不知道啥意思

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<deque>
#include<set>
#include<stack>
#include<bitset>
#include<cstring>
#define ll long long
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
using namespace std;
const int INF=0x3f3f3f3f,N=3000100;

inline int read(){
    int x=0,y=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*y;
}

int e[N],ne[N],h[N],w[N],idx=2;
int f1[N],v[N],pos[N],f2[N],f3[N],f4[N];
int n;

void add(int a,int b,int c){
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}

void dfs(int x,int fa){
    f1[x]=f2[x]=v[x];
    for(int i=h[x];~i;i=ne[i]){
        int j=e[i];
        if(j==fa) continue;
        dfs(j,x);
        f1[x]+=max(f1[j]-(w[i]<<1),0);
    }
    for(int i=h[x];~i;i=ne[i]){
        int j=e[i];
        if(f2[j]-w[i]>0&&j!=fa){
            int tmp=max(f1[j]-(w[i]<<1),0);
            int s=f1[x]-tmp+f2[j]-w[i];
            if(s>f2[x]){
                f3[x]=f2[x];
                f2[x]=s;
                pos[x]=j;
            }else f3[x]=max(f3[x],s);
        }
    }
}

void dfsexroot(int x,int u,int val){
    int j=e[u^1];
    int t=max(f1[j]-(w[u]<<1),0);
    int s=f1[x]+val-w[u];
    f1[x]+=t,f2[x]+=t;
    if(s>f2[x]){
        f3[x]=f2[x];
        f2[x]=s;
        pos[x]=j;
    }else f3[x]=max(f3[x],s);
    for(int i=h[x];~i;i=ne[i]){
        if(i!=(u^1)){
            int k=e[i];
            int tmp=max(f1[k]-(w[i]<<1),0);
            f1[x]-=tmp;
            dfsexroot(k,i,(pos[x]==k?f3[x]:f2[x])-tmp);
            f1[x]+=tmp;
        }
    }
}

int main(){

    memset(h,-1,sizeof h);

    n=read();
    for(int i=1;i<n;i++){
        int a,b,c;
        a=read(),b=read(),c=read();
        add(a,b,c);
        add(b,a,c);
    }

    for(int i=1;i<=n;i++) v[i]=read();

    dfs(1,0);

    dfsexroot(1,0,0);
    
    for(int i=1;i<=n;i++) printf("%d\n",f2[i]);
    return 0;
}
posted @ 2021-05-28 22:32  wsy_jim  阅读(48)  评论(0编辑  收藏  举报