【NOIP2017】Day4

来源:互联网 发布:知荣制衣 联系方式 编辑:程序博客网 时间:2024/05/17 03:17

Solution

T1:首先可以想到分成两组暴搜+剪枝得到所有可能,然后meeting in middle,尴尬的是时间与空间,时间从2s—>5s—>12s(评测时才改的,考试时只到5s),对于时间12s可以直接快排,22667000000 512M可以开两个刚刚好,考场上我以为快排过不了,就写了个基数排序,结果要开三个数组,空间炸了……标称方法是一边224记到数组,之后剩下的枚举也可以过,不过都是10s左右,对于空间上ljn大佬的方法是拿出4个来,剩下的225够开,剩下的4个24枚举即可,加上我的基数排序最慢的点2s也过了。
T2:
网上有题解:
http://blog.csdn.net/longyuepeng/article/details/38521877
http://blog.csdn.net/ypxrain/article/details/72864491
T3:类似POJ消防站一题,我在灰色的果实一题也写过,不过老师好像有另外的解法:f[i][j][k]表示i的水库距离为j,k表示是否在子树内。其实我也不会。

CODE

T1

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int MAXN=34000000;int a[100],b[100],c[2],cnt[1<<17];int x[MAXN],y[MAXN],z[MAXN];int cnta,cntb,cntx,cnty,W,n,ans=0;void dfs1(int k,int sum){    if (sum>W) return;    if (k>cnta)    {        x[++cntx]=sum;        return;    }    dfs1(k+1,sum);    dfs1(k+1,sum+a[k]);}void dfs2(int k,int sum){    if (sum>W) return;    if (k>cntb)    {        y[++cnty]=sum;        return;    }    dfs2(k+1,sum);    dfs2(k+1,sum+b[k]);}void my_sort(int *x,const int &cntx){    //first;    memset(cnt,0,sizeof(cnt));    int bit=(1<<15)-1;    for (int i=1;i<=cntx;i++)        cnt[x[i]&bit]++;    for (int i=1;i<=bit;i++)        cnt[i]=cnt[i-1]+cnt[i];    for (int i=1;i<=cntx;i++)        z[cnt[x[i]&bit]]=x[i],cnt[x[i]&bit]--;    //second;    memset(cnt,0,sizeof(cnt));    for (int i=1;i<=cntx;i++)        cnt[z[i]>>15]++;    for (int i=1,p=1<<16;i<=p;i++)        cnt[i]=cnt[i-1]+cnt[i];    for (int i=cntx;i>=1;i--)        x[cnt[z[i]>>15]]=z[i],cnt[z[i]>>15]--;}void solve(int p){    int j=cnty;    for (int i=1;i<=cntx && j;i++)    {        while (j && x[i]+y[j]+p>W) j--;        if (j) ans=max(ans,x[i]+y[j]+p);            }}int main(){    freopen("brick.in","r",stdin);    freopen("brick.out","w",stdout);    scanf("%d%d",&W,&n);    cnta=n/2-1; cntb=n-n/2-1;    for (int i=1;i<=cnta;i++)        scanf("%d",&a[i]);    for (int i=1;i<=cntb;i++)        scanf("%d",&b[i]);    scanf("%d%d",&c[0],&c[1]);    dfs1(1,0);    dfs2(1,0);    my_sort(x,cntx);    my_sort(y,cnty);    //sort(x+1,x+1+cntx);    //sort(y+1,y+1+cnty);       cntx=unique(x+1,x+1+cntx)-x-1;    cnty=unique(y+1,y+1+cnty)-y-1;    solve(0);    solve(c[0]);    solve(c[1]);    solve(c[0]+c[1]);    printf("%d\n",ans);     return 0;}

T2

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<queue>using namespace std;const int MAXN=50050;int n,Y,u;int w[MAXN],v[MAXN],h[MAXN];double ans;struct node{    double t;    int id;    friend bool operator < (const node &x,const node &y)    {        return x.t>y.t;    }};priority_queue<node>Q;inline double dis(int x,int y){return sqrt(x*x+y*y);}int main(){    freopen("river.in","r",stdin);    freopen("river.out","w",stdout);     scanf("%d%d%d",&n,&Y,&u);    for (int i=1;i<=n;i++)        scanf("%d",&w[i]);    for (int i=1;i<=n;i++)        scanf("%d",&v[i]);    for (int i=1;i<=n;i++)        ans+=w[i]/(double)v[i];    for (int i=1;i<=n;i++)    {        double dd=dis(1,w[i])-w[i];        Q.push((node){dd/v[i],i});    }    Q.push((node){1/(double)u,0});    for (int i=1;i<=Y;i++)    {        int id=Q.top().id;        ans+=Q.top().t;        if (!id) continue;        Q.pop();        h[id]++;        double dd=dis(h[id]+1,w[id])-dis(h[id],w[id]);        Q.push((node){dd/v[id],id});            }    printf("%.4f\n",ans);    return 0;}

T3

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int MAXN=1005;int dis[MAXN][MAXN],dp[MAXN][MAXN],best[MAXN];int c[MAXN],t[MAXN],Head[MAXN];int n,tot=0,ans=0x3f3f3f3f;struct Edge{    int v,next;}edge[MAXN*2];void add_edge(int x,int y){    edge[++tot]=(Edge){y,Head[x]};    Head[x]=tot;}void dfs_dis(int u,int pre,int rt){    for (int i=Head[u];i;i=edge[i].next)    {        int v=edge[i].v;        if (v==pre) continue;        dis[rt][v]=dis[rt][u]+1;        dfs_dis(v,u,rt);        }}void dfs(int u,int pre){    for (int i=Head[u];i;i=edge[i].next)    {        int v=edge[i].v;        if (v==pre) continue;        dfs(v,u);    }    for (int w=1;w<=n;w++)    {        dp[u][w]=c[w]+t[dis[w][u]];        for (int i=Head[u];i;i=edge[i].next)        {            int v=edge[i].v;            if (v==pre) continue;            dp[u][w]+=min(dp[v][w]-c[w],best[v]);           }        best[u]=min(best[u],dp[u][w]);    }   }int main(){    freopen("reservoir.in","r",stdin);    freopen("reservoir.out","w",stdout);    scanf("%d",&n);     for (int i=1;i<=n;i++)        scanf("%d",&c[i]);    for (int i=1;i<=n;i++)        scanf("%d",&t[i]);    for (int i=1;i<n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        add_edge(x,y); add_edge(y,x);           }    for (int i=1;i<=n;i++) dfs_dis(i,0,i);    memset(dp,0x3f,sizeof(dp));    memset(best,0x3f,sizeof(best));    dfs(1,0);    cout<<best[1]<<endl;    return 0;}