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\n",cul(r+1)-cul(l));
        l=read(),r=read();
    }

    return 0;
}
上一篇:linux处理僵尸进程


下一篇:5.24 测试总结