2018年4月24日训练日记

昨晚上的比赛:网站崩了,交了五发就走了

今天重判了一次,除了A都过了。。。(细节错误)迷

基于最近几场比赛非常差的表现,今天又回去重新看了三大DP。

数位DP:

主要优点在于记忆化。这类题目应该是比较好辨认的。。。(现在只会dfs写法了)

1、一段区间内满足给定条件的数的个数。这里条件的改变主要影响dfs的参数以及内部的操作。

2、求一段区间内第几个满足条件的数。这里就用到了二分。

注意:初始化写在外面可能会TLE,是否具有前导0。

求区间内第几个含666的数(数位dp+二分):

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<map>
using namespace std;
const long long INF=0x3f3f3f3f3f3f3f3fll;
long long f[30][6];
int a[30];
int n,m;
int ind;
long long dfs(int pos,int s,bool limit) {
   if(pos==-1) return s==3;
   if(!limit&&f[pos][s]!=-1) return f[pos][s];
   int i,end=limit?a[pos]:9;
   long long ans=0;
    for(i=0; i<=end; i++) {
       int ns=s;
            if(s==2&&i==6) ns=3;
            else if(s==2&&i!=6) ns=0;
            else if(s==1&&i==6) ns=2;
            else if(s==1&&i!=6) ns=0;
            else if(s==0&&i==6) ns=1;
            ans+=dfs(pos-1,ns,limit&&i==end);
            }
        if(!limit) f[pos][s]=ans;
        return ans;
}
long long solve(long long xx){
    int pos=0;
    while(xx){
        a[pos++]=xx%10;
        xx/=10;
    }
    return dfs(pos-1,0,1);
}
long long go(long long n){
    long long fir=0,end=INF;
    long long ans=-1;
    while(fir<=end){
        long long mid=(fir+end)>>1;
        if(solve(mid)<n){
            fir=mid+1;
        }
        else{
            ans=mid;
            end=mid-1;
        }
    }
    return ans;
}
int main() {
    memset(f,-1,sizeof(f));
    int t;
    long long x,y;
    while (scanf("%d",&t)!=EOF) {
    	while (t--){
        scanf("%lld",&x);
        printf("%lld\n",go(x));
    }
    }
    return 0;
}

树形DP:

在树上dp利用dfs完成状态转移。(话说为什么忘得这么快?!赶紧去翻了自己的博客。。。虽然也很迷)

扫描二维码关注公众号,回复: 867446 查看本文章

此类问题我个人还是不好辨认的。不过这类题目都是在树上进行操作,而且有状态转移,这类问题状态转移还是关键也是难点。。。

经典问题:从树上一个点出发所能达到的最远距离。求树的重心(删除该点后使最大的子树的最小)。

从树上一个点出发所能达到的最远距离:(经典)

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int mx=10005;
struct node{
    int w,v,nex;
}a[mx<<1];
int dp[mx][3],h[mx],n,t;
void add(int w,int v,int f)
{
 a[t].w=w;
 a[t].v=v;
 a[t].nex=h[f];
 h[f]=t++;
}
void dfs1(int f);
void dfs2(int f);
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(h,-1,sizeof(h));
        memset(dp,0,sizeof(dp));t=0;
        for(int i=2;i<=n;i++)
        {
         int x,y;
         scanf("%d%d",&x,&y);
         add(y,i,x);
        }
        dfs1(1);dfs2(1);
        for(int i=1;i<=n;i++)printf("%d\n",max(dp[i][2],dp[i][0]));
    }
return 0;
}
void dfs1(int f)
{
    for(int i=h[f];i!=-1;i=a[i].nex)
    {
        int z=a[i].v;
        dfs1(z);
        int w=dp[z][0]+a[i].w;
        if(w>=dp[f][0])
        {
         dp[f][1]=dp[f][0];
         dp[f][0]=w;
        }
        else if(w>dp[f][1]) dp[f][1]=w;
    }
}
void dfs2(int f)
{
    for(int i=h[f];i!=-1;i=a[i].nex)
    {
        int z=a[i].v;
        int w=dp[z][0]+a[i].w;
        if(w==dp[f][0])
        {
         dp[z][2]=max(dp[f][2],dp[f][1])+a[i].w;
        }
        else dp[z][2]=max(dp[f][2],dp[f][0])+a[i].w;
        dfs2(z);
    }
}

状压dp待总结。。。这几天要付出十倍的努力,全力备战省赛。

另:wf告诉我们gets不能随便用了。。。

猜你喜欢

转载自blog.csdn.net/lsd20164388/article/details/80066093