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;
}