NOIP模拟10.27

来源:互联网 发布:5432端口 编辑:程序博客网 时间:2024/06/03 23:01

Poetize10
A.transport(Floyd+状压dp)
先Floyd预处理出两点间最短路径,然后状压dp,dp[s][i]表示状态为s的点都遍历了,停在i的最小时间。枚举一个j去转移就好了。然后处理出f[s],表示遍历了s状态的点的最小花费。然后枚举A遍历了哪些点,B必须遍历了其余点与1.取最大值就是最慢的,更新答案即可。复杂度O(2^n *n*n)
B.elevator(数学+模拟)
C.updown(分层图spfa/背包dp)
这题数据太水了hh,被我假的背包dp水过了。实质上正解应该是分层图spfa。%%%Elijahqi

A

#include <cstdio>#include <cstring>#include <algorithm> using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 20inline ll read(){    ll 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,dp[300000][N],mp[N][N],bin[N],f[300000],ans=inf;//dp[s][i],状态为s的点都便利了,现在在i的最小时间int main(){//  freopen("transport3.in","r",stdin);    n=read();m=read();memset(mp,inf,sizeof(mp));    while(m--){        int x=read(),y=read();mp[x][y]=mp[y][x]=read();    }    for(int i=1;i<=n;++i) mp[i][i]=0;    for(int k=1;k<=n;++k)        for(int i=1;i<=n;++i)            for(int j=1;j<=n;++j)                mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);    memset(dp,inf,sizeof(dp));bin[0]=1;memset(f,inf,sizeof(f));    for(int i=1;i<=n;++i) bin[i]=bin[i-1]<<1;dp[1][1]=0;    for(int s=1;s<bin[n]-1;++s)        for(int i=1;i<=n;++i){            if(dp[s][i]==inf) continue;            for(int j=1;j<=n;++j){                if(s&bin[j-1]||mp[i][j]==inf) continue;                dp[s|bin[j-1]][j]=min(dp[s|bin[j-1]][j],dp[s][i]+mp[i][j]);            }        }    for(int s=0;s<=bin[n]-1;++s)        for(int j=1;j<=n;++j) f[s]=min(f[s],dp[s][j]);    for(int s=0;s<=bin[n]-1;++s){        if(!(s&1)) continue;        int res=max(f[s],f[(bin[n]-1-s)|1]);        ans=min(ans,res);    }printf("%d\n",ans);    return 0;} 

B

#include <cstdio>#include <cstring>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 12inline ll read(){    ll 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,bel[N][N],tot=0,cnt[N*N>>2];ll k;bool ans[N][N],f[N*N>>2];int main(){//  freopen("elevator.in","r",stdin);    n=read();k=read();    for(int i=1;i<=n;++i)        for(int j=1;j<=n;++j){            if(bel[i][j]) continue;            bel[i][j]=++tot;bel[j][n-i+1]=tot;            bel[n-j+1][i]=tot;bel[n-i+1][n-j+1]=tot;        }    for(int i=1;i<=tot;++i) cnt[i]=4;    for(int i=1;i<=n;++i)        for(int j=1;j<=n;++j){            if(f[bel[i][j]]) continue;            if(cnt[bel[i][j]]==1){ans[i][j]=1,f[bel[i][j]]=1;continue;}            ll res=1;cnt[bel[i][j]]--;            for(int ii=1;ii<=tot;++ii) res*=cnt[ii];            if(k>res) k-=res,ans[i][j]=1,f[bel[i][j]]=1,cnt[bel[i][j]]=1;        }    for(int i=1;i<=n;++i){        for(int j=1;j<=n;++j) printf("%d",ans[i][j]);puts("");    }    return 0;}

C

骗分背包版

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 1010inline ll read(){    ll 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[30],dp[N][30],st=0;//dp[i][j],到i层,手柄停留在j槽的最小花费inline int abs(int x){return x<0?-x:x;} int main(){//  freopen("updown.in","r",stdin);    n=read();m=read();memset(dp,inf,sizeof(dp));    for(int i=1;i<=m;++i) c[i]=read();    for(int i=1;i<=m;++i) if(!c[i]) st=i;dp[1][st]=0;    for(int j=st+1;j<=m;++j)        for(int i=c[j]+1;i<=n;++i)            for(int k=st;k<=m;++k)                dp[i][j]=min(dp[i][j],dp[i-c[j]][k]+abs(j-k)+c[j]*2);    for(int j=st-1;j>=1;--j)        for(int i=n+c[j];i>=1;--i)            for(int k=1;k<=m;++k)                dp[i][j]=min(dp[i][j],dp[i-c[j]][k]+abs(j-k)-c[j]*2);    for(int j=st+1;j<=m;++j)        for(int i=c[j]+1;i<=n;++i)            for(int k=1;k<=m;++k)                dp[i][j]=min(dp[i][j],dp[i-c[j]][k]+abs(j-k)+c[j]*2);    int ans=inf;for(int j=1;j<=m;++j) ans=min(ans,dp[n][j]);    if(ans==inf) puts("-1");    else printf("%d\n",ans);    return 0;}

正解spfa版

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 1010#define pa pair<int,int>inline 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],h[N*30],num=0,d[N*30],ans=inf;bool inq[N*30];struct edge{    int to,next,val;}data[N*30*30];inline void add(int x,int y,int val){    data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;}void spfa(int s){    queue<int>q;memset(inq,0,sizeof(inq));memset(d,inf,sizeof(d));    q.push(s);d[s]=0;inq[s]=1;    while(!q.empty()){        int x=q.front();q.pop();inq[x]=0;        for(int i=h[x];i;i=data[i].next){            int y=data[i].to;            if(d[x]+data[i].val<d[y]){                d[y]=d[x]+data[i].val;                if(!inq[y]) q.push(y),inq[y]=1;            }        }    }}int main(){//  freopen("updown.in","r",stdin);    n=read();m=read();    for(int i=1;i<=m;++i) c[i]=read();    for(int i=1;i<=n;++i)        for(int j=1;j<=m;++j)            for(int k=1;k<=m;++k)                if(i+c[k]>=1&&i+c[k]<=n)                     add((i-1)*m+j,(i+c[k]-1)*m+k,abs(j-k)+abs(c[k])*2);    for(int i=1;i<=m;++i) if(!c[i]) spfa(i);    for(int i=1;i<=m;++i) ans=min(ans,d[(n-1)*m+i]);    if(ans==inf) puts("-1");    else printf("%d\n",ans);    return 0;}
原创粉丝点击