2021.5.29 讲题日

不要问我为啥鸽到6.5

Program in C++14

T1:\(P1474\)

一道完全背包

就一元一元的凑

易得状态转移方程:

\[f[j]+=f[j-m[i]]; \]

其中 \(f[j]\) 代表凑成 \(j\) 元有 \(f[j]\) 种方法, \(m[i]\) 代表第 \(i\) 个货币的面值

#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
#include<chrono>
#include<random>
#include<unordered_map>
using namespace std;

#define ll long long
#define ull unsigned long long
#define rll register long long
#define ri register int
//#define int long long

const int N=10000010;
int v,n;
int m[N];
ll f[N];

inline ll read(){
    ll 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;
}

signed main(){
	f[0]=1;
	v=read(),n=read();
	for(ri i=1;i<=v;i++)
		m[i]=read();
	for(ri i=1;i<=v;i++)
		for(ri j=m[i];j<=n;j++)
			f[j]+=f[j-m[i]];
	printf("%lld",f[n]);
	return 0;
}

T2:\(P1060\)

裸!到!不!能!再!裸!一!裸!到!底!的!0!1!背!包!

看这个顺便交一下吧

#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
#include<chrono>
#include<random>
#include<unordered_map>
using namespace std;

#define ll long long
#define ull unsigned long long
#define rll register long long
#define ri register int
//#define int long long

const int N=310000;
int n,m;
int v[N],w[N],p[N],f[N];

inline ll read(){
    ll 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;
}

signed main(){
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		v[i]=read(),w[i]=read();
		p[i]=w[i]*v[i];
	}
	for(int i=1;i<=m;i++)
        for(int j=n;j>=v[i];j--)
            f[j]=max(f[j],f[j-v[i]]+p[i]);
    printf("%d",f[n]);
	return 0;
}

T3:\(P1352\)

不知道为什么反正看到这道题就让我想到

其实在某次模拟考中有这道题,就是兔子家族那道

模板题!!!!!!!!!!!!!!!

题中指出了给出的关系是树,相互有依赖关系,又让最大值,显然的树状 \(dp\ !\)

一种是\(A\)君来,\(ta\)的部下不来的指数,用\(1\)表示;一种是\(A\)君不来,\(ta\)的部下来的指数,用\(0\)表示;

易得状态转移方程:

\[f[x][1]=max(max(f[x][1],f[x][1]+f[i][0]),f[i][0]); \]

\[f[x][0]=max(max(f[x][0],f[i][1]+f[x][0]),max(f[i][1],f[i][0])); \]

其中 \(x\) 为枚举到的来或者不来的人, \(i\)\(x\) 的直接下属,递归一下即可

#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
#include<chrono>
#include<random>
#include<unordered_map>
using namespace std;

#define ll long long
#define ull unsigned long long
#define rll register long long
#define ri register int
//#define int long long

const int N=6010;
int n,root;
int f[N][2];
struct tree{
	int rt,up,dn;
}t[N];

inline ll read(){
    ll 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;
}

void work(int x){
	for(int i=t[x].dn;i;i=t[i].up){
		work(i);
		f[x][1]=max(max(f[x][1],f[x][1]+f[i][0]),f[i][0]);
        f[x][0]=max(max(f[x][0],f[i][1]+f[x][0]),max(f[i][1],f[i][0]));
	}
}

int main(){
	n=read();
	for(int i=1;i<=n;i++)
		f[i][1]=read();
	for(int i=1;i<=n-1;i++){
		int l,k;
		l=read(),k=read();
			t[l].rt++;
			t[l].up=t[k].dn;
			t[k].dn=l;
	}
	for(int i=1;i<=n;i++){
		if(t[i].rt==0){
			root=i;
			break;
		}
	}
	work(root);
	printf("%d",max(f[root][0],f[root][1]));
	return 0;
}
posted @ 2021-07-14 20:02  BFNewdawn  阅读(31)  评论(0编辑  收藏  举报