2模02day1题解
源文件在我的网盘上。
(只有机智的人才能看到我的链接)
机智的双重下划线~~~![]()
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\n",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\n",qh,a);
iq[a]=0;
for(b=head[a];b!=0;b=next[b]){
//printf("Access #%d: pre dist %d , suf dist %d\n",to[b],f[to[b]],f[a]+len[b]);
if(f[a]+len[b]<f[to[b]]){
//printf("Relax #%d\n",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 \n");
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\n",f[n]);
return 0;
}
T3
一道机智的二分题目
先二分答案,再用DP检测答案是否可以。符合单调性(废话)。
DP方程:
$F\left[ i,j\right] =max \left\{\left\lfloor \frac{s-k\cdot a_i}{b_i} \right\rfloor +F\left[ i-1,j-k\right] \forall k \in \left[ 0,min\left\{ \left\lfloor \frac{s}{a_i} \right\rfloor ,j \right\}\right]\right\}$
//上代码
#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\n",ans);
return 0;
}

浙公网安备 33010602011771号