zoukankan      html  css  js  c++  java
  • 2021.06.02模拟赛DP2

    题面

    T1 多边形

    就A了这一道/kk
    疯狂的小细节:

    1. 这是个环!要断成链!!
    2. 你看样例里那个-7多显眼有没有什么启发?负数乘负数!乘完可能是个很大的正数!!
    3. 同时记录最大值最小值,赋初值要注意反着赋!求最小就先赋最大,求最大先赋最小
    4. DP的顺序已经有保证了,没必要再开bool数组判当前点和边用没用过一开始被这个绕进去半天

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define maxn 110
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    const int inf=0x7fffffff;
    int n,p[maxn];
    char e[maxn];
    bool flag_e[maxn],flag_p[maxn];//没用!! 
    int ans,f[maxn][maxn][2],s[10],minn,maxx;
    
    void dp(){
    	for(int j=2;j<=n;j++){
    		for(int i=1;i<=n;i++){
    			for(int k=1;k<j;k++){
    				
    				int a=f[i][k][0],b=f[i][k][1],t=(i+k-1)%n+1,c=f[t][j-k][0],d=f[t][j-k][1];
    				if(e[t]=='t') minn=a+c,maxx=b+d;
    				else{
    					s[1]=a*c,s[2]=a*d,s[3]=b*c,s[4]=b*d;
    					minn=s[1];maxx=s[1];
    					for(int o=2;o<=4;o++){
    						minn=min(minn,s[o]);
    						maxx=max(maxx,s[o]);
    					}
    				}
    				
    				f[i][j][0]=min(f[i][j][0],minn);
    				f[i][j][1]=max(f[i][j][1],maxx);
    			}
    		}
    	}
    }
    
    int main(){
    	read(n);
    	for(int i=1;i<=n;i++) {
    		cin>>e[i]>>p[i];
    		f[i][1][0]=p[i];f[i][1][1]=p[i];
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=2;j<=n;j++){
    			f[i][j][0]=inf;//i为开头,长度为j的最小值 
    			f[i][j][1]=-inf;//i为开头,长度为j的最大值 
    		}
    	}
    	dp();
    	ans=-inf;
    	for(int i=1;i<=n;i++) ans=max(ans,f[i][n][1]);
    	cout<<ans<<endl;
    	return 0;
    }
    /*
    4
    t -7 t 4 x 2 x 5
    */
    //33
    

    T2 龙妹妹买牛奶

    因为k只有1和2,所以从k入手分类讨论(不会k<=100和k<=n的情况,等神仙来讲)

    1. k==1 就是没有上司的舞会,父亲选了儿子就不能选
    2. k==2 在1上稍加修改,父亲选了儿子孙子都不能选f[x][1]+=sum[y];
      父亲不选,儿子可选0或1个,取个maxf[x][0]=max(f[x][0],f[y][1]+sum[x]-f[y][0]);
    3. 我们也不知道一号点是选好还是不选好,就最后再取个max

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define maxn 100010
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    int n,k,a[maxn],b[maxn];
    int f[maxn][2];//0不选 1选 
    int cnt=1,head[maxn],rt[maxn],root,ans,sum[maxn];
    bool vis[maxn];
    struct node{
    	int nxt;
    	int to;
    }e[2*maxn];
    
    void add(int from,int to){
    	e[++cnt].to=to;
    	e[cnt].nxt=head[from];
    	head[from]=cnt;
    }
    
    void dp1(int x){
    	for(int i=head[x];i;i=e[i].nxt){
    		int y=e[i].to;
    //		cout<<"y"<<y<<"  ";
    		dp1(y);
    		f[x][1]+=f[y][0];
    		f[x][0]+=max(f[y][0],f[y][1]);
    //		cout<<"f[x][]"<<f[x][1]<<" "<<f[x][0]<<endl;
    	} 
    }
    
    void dp2(int x,int fa){
    	for(int i=head[x];i;i=e[i].nxt){
    		int y=e[i].to;
    		if(y==fa) continue;
    		dp2(y,x);
    		sum[x]+=f[y][0];
    	}
    	f[x][0]=sum[x];
    	for(int i=head[x];i;i=e[i].nxt){
    		int y=e[i].to;
    		if(y==fa) continue;
    		f[x][0]=max(f[x][0],f[y][1]+sum[x]-f[y][0]);
    		f[x][1]+=sum[y];
    	}
    }
    
    int main(){
    	read(n),read(k);
    	if(k==1){
    		for(int i=1;i<=n;i++) f[i][0]=0,f[i][1]=1;
    		for(int i=1;i<=n-1;i++){
    			read(a[i]),read(b[i]);
    			if(a[i]>b[i]) swap(a[i],b[i]);
    			add(a[i],b[i]);
    			rt[b[i]]=1;
    		}
    		for(int i=1;i<=n;i++){
    			if(rt[i]==0){
    				root=i;
    				break;
    			}
    		}
    		dp1(root);
    		ans=max(f[root][0],f[root][1]);
    	}
    	if(k==2){
    		for(int i=1;i<=n;i++) f[i][0]=0,f[i][1]=1;
    		for(int i=1;i<=n-1;i++){
    			read(a[i]),read(b[i]);
    			add(a[i],b[i]);
    			add(b[i],a[i]);
    		}
    		dp2(1,0);
    		ans=max(f[1][0],f[1][1]);
    	}
    	cout<<ans<<endl;
    	return 0;
    }//100pts
    /*
    3 1
    1 2
    1 3
    */
    //2
    /*
    3 2
    1 2
    1 3
    */
    //1
    

    T3 不要62

    数位DP果然全是细节,不过经过本题爆零后对数位DP的理解又深了不少

    写法1

    solve(x)//[0,x]有多少符合要求的数

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define maxn 20
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0;bool flag=0;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    int n,m;
    int ans,len,num[maxn],f[maxn][maxn];
    bool flag=0;
    
    void pre(){
    	memset(f,0,sizeof(f));
    	f[0][0]=1;
    	for(int i=1;i<=9;i++){
    		for(int j=0;j<=9;j++){
    			if(j==4) continue;
    			for(int k=0;k<=9;k++){
    				if(!(j==6&&k==2)) f[i][j]+=f[i-1][k];
    			} 
    		}
    	}
    }
    
    int solve(int x){
    	if(!x) return 1;//********
    	memset(num,0,sizeof(num));
    	ans=0,len=0;
    	while(x){
    		num[++len]=x%10;
    		x/=10;
    	}
    //	num[++len]=0;
    	for(int i=len;i>=1;i--){
    		for(int j=0;j<num[i];j++){
    			if(!(num[i+1]==6&&j==2)) ans+=f[i][j];	
    		}
    		if((num[i]==4)||(num[i+1]==6&&num[i]==2)) break;
    		if(i==1) ++ans; //如果这个数自己是满足条件的,就把它也算上********
    	}
    	return ans;
    }
    
    int main(){
        pre();
    	while(1){
    		read(n),read(m);
    		if(n==0&&m==0) return 0;
    		if(m<n) swap(n,m);
    //		cout<<"**"<<solve(m)<<"**"<<solve(n-1)<<endl;
    		cout<<solve(m)-solve(n-1)<<endl;
    	}
    	return 0;
    }
    /*
    1 100
    233 2333333
    0 0
    */
    //80
    //1187893
    /*
    1 9999999
    */
    //4435928(?
    /*
    4 4
    */
    //0!!!
    

    写法2

    (来自wsy_jim)
    cul[x]//[0,x)有多少符合要求的数

    code:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=15;
    
    inline int read(){
        int 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;
    }
    
    int l,r,f[N][N];
    
    void init(){
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(int len=1;len<=7;len++)
            for(int i=0;i<10;i++)
                for(int j=0;j<10;j++)
                    if(i!=4&&!(i==6&&j==2)) f[len][i]+=f[len-1][j];
    }
    
    int cul(int x){
        int op[N],len=0,res=0;
        int n=x;
        while(n){
            op[++len]=n%10;
            n/=10;
        }
        op[len+1]=0;
        for(int i=len;i>0;i--){
            for(int j=0;j<op[i];j++){
                if(j!=4&&!(j==2&&op[i+1]==6)) res+=f[i][j];
            }
            if(op[i]==4||(op[i]==2&&op[i+1]==6)) break;
        }
        return res;
    }
    
    int main(){
    
        init();
    
        l=read(),r=read();
        while(l!=0||r!=0){
            //do something...
    //        cout<<cul(r+1)<<" "<<cul(l)<<endl;
            printf("%d
    ",cul(r+1)-cul(l));
            l=read(),r=read();
        }
    
        return 0;
    }
    
  • 相关阅读:
    前端开发中的设计模式
    前端常见的攻击
    前端笔试题
    JavaScript中的回调地狱及解决方法
    JavaScript中的编码解码
    JavaScript中操作节点
    前端常见面试题
    Vue的使用总结(2)
    JavaScript中的事件
    Vue的使用总结(1)
  • 原文地址:https://www.cnblogs.com/DReamLion/p/14847445.html
Copyright © 2011-2022 走看看