NOIP2003提高组

来源:互联网 发布:武汉软件外包公司 编辑:程序博客网 时间:2024/05/21 22:42

2003提高
A.神经网络(拓扑模拟)
B.侦探推理(字符串+模拟) 太恶心了,不会写。
C.加分二叉树(区间dp+树的遍历)
因为中序遍历是1~n,所以如果根是k的话,左子树一定是1~k-1,右子树一定是k+1~n。这样就可以区间dp了。顺道记一下跟,方便输出前序遍历
D.传染病控制(搜索+剪枝)
实质上相当于在每层选一条边砍掉,可以爆搜,加个最优性剪枝。注意一个点安全了,只要它的祖先有一个安全了即可。

A

#include <bits/stdc++.h>using namespace std;#define N 110#define ll long long#define inf 0x3f3f3f3finline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,m,c[N],u[N],h[N],num=0,du[N];bool ans[N],flag=0;struct edge{    int to,next,val;}data[N*N];int main(){//  freopen("a.in","r",stdin);    n=read();m=read();    for(int i=1;i<=n;++i) c[i]=read(),u[i]=read();    while(m--){        int x=read(),y=read(),val=read();du[y]++;        data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;    }queue<int>q;    for(int i=1;i<=n;++i) if(!du[i]) q.push(i),u[i]=0;    while(!q.empty()){        int x=q.front();q.pop();c[x]-=u[x];if(!h[x]) ans[x]=1;        for(int i=h[x];i;i=data[i].next){            int y=data[i].to;if(--du[y]==0) q.push(y);            if(c[x]<=0) continue;c[y]+=c[x]*data[i].val;        }    }for(int i=1;i<=n;++i)        if(ans[i]&&c[i]>0) printf("%d %d\n",i,c[i]),flag=1;    if(!flag) puts("NULL");    return 0;}

C

#include <bits/stdc++.h>using namespace std;#define N 35#define ll long long#define inf 0x3f3f3f3finline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,a[N],rt[N][N];ll dp[N][N];//dp[i][j],编号为i~j的的点构成的树的最大加分void print(int l,int r){    if(l>r) return;    if(l==r){printf("%d ",l);return;}    printf("%d ",rt[l][r]);    print(l,rt[l][r]-1);print(rt[l][r]+1,r);}int main(){    freopen("a.in","r",stdin);    n=read();for(int i=1;i<=n;++i) a[i]=read();    for(int i=1;i<=n+1;++i) dp[i][i-1]=1;    for(int i=1;i<=n;++i) dp[i][i]=a[i],rt[i][i]=i;    for(int len=2;len<=n;++len)        for(int i=1;i+len-1<=n;++i){            int j=i+len-1;            for(int k=i;k<=j;++k)                if(dp[i][k-1]*dp[k+1][j]+a[k]>dp[i][j])                    dp[i][j]=dp[i][k-1]*dp[k+1][j]+a[k],rt[i][j]=k;        }printf("%lld\n",dp[1][n]);    print(1,n);return 0;}

D

#include <bits/stdc++.h>using namespace std;#define N 310#define ll long long#define inf 0x3f3f3f3finline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,owo,h[N],num=0,dep[N],fa[N],ans=inf;bool mk[N];vector<int>a[N];struct node{    int to,next;}data[N<<1];void dfs1(int x){    for(int i=h[x];i;i=data[i].next){        int y=data[i].to;if(fa[x]==y) continue;        fa[y]=x;dep[y]=dep[x]+1;a[dep[y]].push_back(y);dfs1(y);    }}void dfs(int deep,int res){    if(res>=ans) return;    int cnt=0;    for(int i=0;i<a[deep].size();++i){        int x=a[deep][i];        while(fa[x]) if(mk[x]) break;else x=fa[x];        if(x==1) ++cnt;else mk[a[deep][i]]=1;    }if(!cnt){ans=res;return;}    for(int ii=0;ii<a[deep].size();++ii){        int x=a[deep][ii];if(mk[x]) continue;        mk[x]=1;dfs(deep+1,res+cnt-1);mk[x]=0;    }for(int i=0;i<a[deep].size();++i){        int x=a[deep][i];if(mk[x]) mk[x]=0;    }}int main(){//  freopen("a.in","r",stdin);    n=read();owo=read();    while(owo--){        int x=read(),y=read();        data[++num].to=y;data[num].next=h[x];h[x]=num;        data[++num].to=x;data[num].next=h[y];h[y]=num;    }dfs1(1);dfs(1,1);    printf("%d\n",ans);    return 0;}
原创粉丝点击