2/20 树上dp+正方形个数问题(dp)+dfs+连通块+背包

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2/20 树上dp+正方形个数问题(dp)+dfs+连通块+背包相关的知识,希望对你有一定的参考价值。

P1352 没有上司的舞会
https://www.luogu.com.cn/problem/P1352

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e6+5;
struct node

    int  to,nxt;
e[maxn];
int n,r[maxn],f[maxn][4],head[maxn],cnt,in[maxn];
void add(int from,int to)

    e[++cnt].to=to;
    e[cnt].nxt=head[from];
    head[from]=cnt;

void dfs(int u)

    for(int i=head[u];i;i=e[i].nxt)
    
        int v=e[i].to;
        dfs(v);
        f[u][0]+=max(f[v][0],f[v][1]);
        f[u][1]+=f[v][0];
    
    f[u][1]+=r[u];

int main()

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&r[i]);
    for(int i=1;i<=n-1;i++)
    
        int u,v;scanf("%d%d",&u,&v);
        in[u]++; //入度
        add(v,u);
    
    int g;
    for(int i=1;i<=n;i++)
    
        if(!in[i])
        
            g=i;
            break;
        
    
    dfs(g);  //从根开始,因此跟记录最大值
    cout<<max(f[g][0],f[g][1])<<endl;  
    return 0;

https://www.luogu.com.cn/problem/P2014

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e3+5;
struct node

    int  to,nxt;
e[maxn];
int n,m,r[maxn],f[maxn][maxn],head[maxn],cnt,in[maxn];
void add(int from,int to)

    e[++cnt].to=to;
    e[cnt].nxt=head[from];
    head[from]=cnt;

void dfs(int u,int num)

    if(num<=0) return;
    for(int i=head[u];i;i=e[i].nxt)
    
        int v=e[i].to;
        for(int j=0;j<num;j++)
            f[v][j]=f[u][j]+r[v]; //加上当前结点的值
        dfs(v,num-1);
        for(int j=1;j<=num;j++)
            f[u][j]=max(f[u][j],f[v][j-1]);
    

int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    
        int v;scanf("%d%d",&v,&r[i]);
        add(v,i);
    
    dfs(0,m);
    cout<<f[0][m]<<endl;
    return 0;

https://www.luogu.com.cn/problem/P2733

#include <bits/stdc++.h>

using namespace std;
const int maxn=300;
char mp[maxn][maxn];
bool vis[maxn][maxn];
int n,f[maxn][maxn],num[100005];

int main()

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        cin>>mp[i][j];
    for(int i=1;i<=n;i++)
    
        for(int j=1;j<=n;j++)
        
            if(mp[i][j]=='1')
                f[i][j]=min(f[i-1][j],min(f[i][j-1],f[i-1][j-1]))+1;
            num[f[i][j]]++;
        
    
    for(int i=n;i>=1;i--)
        num[i-1]+=num[i];
    for(int i=2;i<=n;i++)
    
        if(num[i])
            cout<<i<<" "<<num[i]<<endl;
    
    return 0;

https://www.luogu.com.cn/problem/P2040

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e2+5;
int mp[5][5],ans,tmp=10;
bool vis[maxn][maxn];
void change(int x,int y)

    mp[x][y]^=1;
    mp[x+1][y]^=1;
    mp[x-1][y]^=1;
    mp[x][y+1]^=1;
    mp[x][y-1]^=1;

void dfs(int step)

    if(step>tmp)
        return;
    int s=0;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            s+=mp[i][j];
    if(s==9)
    
        ans=step-1;
        if(tmp>ans)
            tmp=ans;
    
    for(int i=1;i<=3;i++)
    
        for(int j=1;j<=3;j++)
        
            change(i,j);
            dfs(step+1);
            change(i,j); //回溯
        
    
    return;

int main()

    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            cin>>mp[i][j];
    dfs(1);
    cout<<tmp<<endl;
    return 0;

https://www.luogu.com.cn/problem/P2052
上连通块-下连通块 的绝对值乘以距离的和
(采用深搜)
num 记录以i为根的子树的大小

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e6+5;
int n,m,num[maxn],f[maxn],head[maxn],cnt,ans;
struct node

    int  to,dis,nxt;
e[maxn];
void add(int from,int to,int dis)

    e[++cnt].to=to;
    e[cnt].dis=dis;
    e[cnt].nxt=head[from];
    head[from]=cnt;

void dfs(int u,int pre)

    num[u]=1;
    for(int i=head[u];i;i=e[i].nxt)
    
        int v=e[i].to;
        if(v==pre)
            continue;
        dfs(v,u);
        num[u]+=num[v];
        ans+=e[i].dis*abs(2*num[v]-n);
    

signed main()

    scanf("%lld",&n);
    for(int i=1;i<=n-1;i++)
    
        int u,v,w;scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    
    dfs(1,0);
    cout<<ans<<endl;
    return 0;

https://www.luogu.com.cn/problem/P2214
记录每个牧场真是音量
其中f[i]表示音量为i的最小奶牛数,然后用音量最大的牧场进行完全背包。
最后加上每个牧场音量的最小奶牛数目

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e6+5;
const int inf=0x3f3f3f3f;
int n,b,v[maxn],w[maxn],g[maxn],f[maxn],mx,ans;

int main()

    scanf("%d%d",&n,&b);
    for(int i=1;i<=b;i++)
        scanf("%d",&v[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
    for(int i=1;i<=n;i++)
    
        g[i]=w[i]-max(w[i-1]-1,0);
        mx=max(mx,g[i]);
    
    memset(f,inf,sizeof(f));
    f[0]=0;
    for(int i=1;i<=b;i++)   //农场数
    
        for(int j=v[i];j<=mx;j++)
            f[j]=min(f[j],f[j-v[i]]+1);
    
    for(int i=1;i<=n;i++)
    
        ans+=f[g[i]];
    
    cout<<ans<<endl;
    return 0;


以上是关于2/20 树上dp+正方形个数问题(dp)+dfs+连通块+背包的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 682C Alyona and the Tree (树上DFS+DP)

HZOJ 20190727 T2 单(树上dp+乱搞?+乱推式子?+dfs?)

树形DP

单(树上DP+乱搞)

牛客练习赛1 树 dp + dfs序

BZOJ3679数字之积 DFS+DP