2模02day1题解

源文件在我的网盘上。链接:http://pan.baidu.com/s/1qWPUDRm 密码:k52e

(只有机智的人才能看到我的链接)

机智的双重下划线~~~

T1

T1就是一个递推,这题目把我恶心到了。。。用double即可。上 代码。

#include <cstring>
#include <cstdio>
int n,i,j,k,m,l,t,v,u,s,d;
int coml[2000],comr[2000],man;
double mat[2000][2000],mat2[2000],mat3[2000],ma;
#define ubit 0xffffffff
int main(){
	freopen("elimination.in","r",stdin);
	freopen("elimination.out","w",stdout);
	scanf("%d",&n);
	m=1<<n;
	for(i=0;i<m;++i){
		mat2[i]=1.0;
		coml[i]=i^1;
		comr[i]=i^1;
		for(j=0;j<m;++j){
			scanf("%d",&k);
			mat[i][j]=(k+0.0)/100;
		}
	}
	for(i=1;i<=n;++i){
		u=1<<i;
		t=(ubit>>(i+1))<<(i+1);
		for(j=0;j<m;++j){
			mat3[j]=0.0;
			for(k=coml[j];k<=comr[j];++k){
				mat3[j]+=mat2[k]*mat[j][k];
			}
			mat3[j]*=mat2[j];
			l=coml[j]&t;
			if(u&coml[j]){
				coml[j]=l;
				comr[j]=l+u-1;
			}else{
				l|=u;
				coml[j]=l;
				comr[j]=l+u-1;
			}
		}
		for(j=0;j<m;++j){
			mat2[j]=mat3[j];
		}
	}
	ma=mat2[0];
	for(i=1;i<m;++i){
		if(mat2[i]>ma){
			ma=mat2[i];
			man=i;
		}
	}
	printf("%d
",man+1);
	return 0;
}

T2

差分约束系统。。。调得我快Shit了(然后。。我会告诉你我还没过么?)

上 代码。

#include <cstdio>
#include <cstring>
#define lowbit(x) (x&-x)
int next[40000],to[40000],f[40000],len[40000],head[40000],hl,i,j,k,h;
int ip,a,b,c,pp[40000],ppl,n;
inline void addEdge(int f,int t,int w){
	++hl;
	next[hl]=head[f];
	to[hl]=t;
	len[hl]=w;
	head[f]=hl;
}
int q[400000],qt,qh;
bool iq[40000];
void spfa(){
	memset(f,0x7f,sizeof f);
	qh=0;
	qt=1;
	iq[n+1]=1;
	q[0]=n+1;
	f[n+1]=0;
	while(qh!=qt){
		a=q[qh];
		//printf("( %d ):#%d
",qh,a);
		iq[a]=0;
		for(b=head[a];b!=0;b=next[b]){
			//printf("Access #%d: pre dist %d , suf dist %d
",to[b],f[to[b]],f[a]+len[b]);
			if(f[a]+len[b]<f[to[b]]){
				//printf("Relax #%d
",to[b]);
				f[to[b]]=f[a]+len[b];
				if(!iq[to[b]]){
					iq[to[b]]=true;
					q[qt++]=to[b];
				}
			}
		}
		++qh;
	}
}
int main(){
	freopen("trees.in","r",stdin);
	freopen("trees.out","w",stdout);
	scanf("%d%d",&n,&h);
	//printf("1 
");
	for(i=0;i<h;++i){
		scanf("%d%d%d",&a,&b,&c);
		addEdge(b,a-1,-c);
	}
	//printf("2 ");
	for(i=0;i<=n;++i) addEdge(n+1,i,0);
	for(i=0;i<n;++i){
		addEdge(i,i+1,1);
		addEdge(i+1,i,0);
	}
	spfa();
	a=0x7fffffff;
	for(i=0;i<=n;++i) if(f[i]<a) a=f[i];
	for(i=0;i<=n;++i) f[i]-=a;
	printf("%d
",f[n]);
	return 0;
}

T3

一道机智的二分题目

先二分答案,再用DP检测答案是否可以。符合单调性(废话)。

DP方程:

$Fleft[ i,j ight] =max left{leftlfloor frac{s-kcdot a_i}{b_i} ight floor +Fleft[ i-1,j-k ight]  forall k in left[ 0,minleft{ leftlfloor frac{s}{a_i} ight floor ,j ight} ight] ight}$

//上代码
#include <cstdio>
#include <cstring>
int n,m,i,j,k,l,r,ans,mid,t;
int p[1000][2],f[2][1000];
int now,pp,t2;
bool dp(int s){
	memset(f,-1,sizeof f);
	now=0,pp=1;
	f[0][0]=0;
	for(i=0;i<n;++i){
		now = pp^now;
		pp =  pp^now;
		now = pp^now;
		for(j=0;j<=m;++j){
			t=s/p[i][0];
			t=t<j?t:j;
			for(k=0;k<=t;++k){
				if(f[pp][j-k]!=-1){
					t2=(s-k*p[i][0])/p[i][1]+f[pp][j-k];
					f[now][j]=(f[now][j]<t2?t2:f[now][j]);
				}
			}
		}
	}
	return f[now][m]>=m;
}
int main(){
	freopen("software.in","r",stdin);
	freopen("software.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(i=0;i<n;++i){
		scanf("%d%d",p[i],p[i]+1);
	}
	l=0,r=0x7fffffff;
	while(l<=r){
		if(dp(mid=(l+r)/2)){
			ans=mid;
			r=mid-1;
		}else{
			l=mid+1;
		}
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/tmzbot/p/3960511.html