Codeforces Round #627 (Div. 3) F. Maximum White Subtree E. Sleeping Schedule

题目:F. Maximum White Subtree
题意:给定一棵树,节点只为黑或者白,问每一个节点的的子树(连通块)中max(白节点个数-黑节点的个数);

把白节点的的值定1,黑的为-1,即计算价值最大,树形dp,联系子,父节点的关系,可直接以i为根进行dp,dp1[i]表示以i为父节点向下max(白-黑),先从下至上做一个dp1记录子节点的max;
还有节点的父节点这边的最大连通块没有确定,比方说val是通过父节点的获得的价值,val<=0的时候表示没有必要加入他的价值给子节点,val>0的时候加入增加子节点的价值,而dp1[i]负数最大就是自己本身-1是一定要算的,进而加上dp1[root]即可。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
int a[200100];
bool vis[200100];
vector<int>hh[200100];
int dp1[200100];
int dp2[200100];
void dfs1(int root,int fa)
{
    if(vis[root])
        return ;
    vis[root]=true;
    dp1[root]=a[root];
        for(int i=0;i<hh[root].size();i++)
        {
            int v=hh[root][i];
            if(v!=fa&&!vis[v])
            {
                dfs1(v,root);
                dp1[root]+=max(0,dp1[v]);
            }
        }
}
void dfs2(int root,int fa)
{
    if(vis[root])
        return ;
    vis[root]=true;
    dp2[root]=dp1[root]+max(0,dp2[fa]-max(0,dp1[root]));
        for(int i=0;i<hh[root].size();i++)
        {
            int v=hh[root][i];
            if(v!=fa&&!vis[v])
            {
                dfs2(v,root);
            }
        }
}
int main()
{
    int n,i,j,l,r,h;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(a[i])
            a[i]=1;
        else
            a[i]=-1;
    }
    for(i=1;i<=n-1;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        hh[x].push_back(y);
        hh[y].push_back(x);
    }
    memset(vis,false,sizeof(vis));
    dfs1(1,-1);
    memset(vis,false,sizeof(vis));
    dfs2(1,-1);
    for(i=1;i<=n;i++)
    {
        printf("%d ",dp2[i]);
    }
    return 0;
}

题目:E. Sleeping Schedule
题意:有n个睡眠时间的选择,可以选择a[i]或者a[i]-1 小时之后开始睡觉,如果在l-r时间段开始睡觉则是好的睡眠,一睡h小时(也就是一天)。

一开始想用a[i]或者a[i]-1状态去进行dp,但是发现状态存储情况比较多,可以看到h(一天有h小时)并不大,将二维的状态改成h就可以了。
dp[i][j]:表示第i次 开始睡眠在j时的时候的好睡眠次数最大值。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
int a[2010];
int dp[2010][2010];   
int book[2010];
int main()
{
    memset(book,0,sizeof(book));
    memset(dp,0,sizeof(dp));
    int n,i,j,l,r,h;
    scanf("%d %d %d %d",&n,&h,&l,&r);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
        int ans=0;
    dp[0][0]=1;
    for(i=1;i<=n;i++)
    {
        for(j=0;j<h;j++)
        {
            if(dp[i-1][j])
            {
                bool flag=false;
                int temp;
                temp=(j+a[i])%h;
                if(temp>=l&&temp<=r)
                dp[i][temp]=max(dp[i][temp],dp[i-1][j]+1);
                else
                dp[i][temp]=max(dp[i][temp],dp[i-1][j]);
                temp=(j+a[i]-1)%h;
                if(temp>=l&&temp<=r)
                dp[i][temp]=max(dp[i][temp],dp[i-1][j]+1);
                else
                dp[i][temp]=max(dp[i][temp],dp[i-1][j]);
            }
        }
    }
    for(i=0;i<h;i++)
        ans=max(ans,dp[n][i]);
    printf("%d",ans-1);
    return 0;
}

发布了72 篇原创文章 · 获赞 19 · 访问量 7497

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/104837203