神仙造计算机题。。。计算机造计算机
subtask 1:
理解了这个题的应该都能写出来。
node 1 read 0 a write a 0
subtask 2:
看到只有一个计算机,内存还只有两个数就明显不能真算了,打表出斐波那契数列,注意要求周期尽量少,所以应该用jmp语句来打表。
1 node 1 2 read 0 a 3 add a 4 4 jmp a//可以对照行号看一下,a+4行对应的就是相应的第a项 5 write 0 0 6 write 1 0 7 write 1 0 8 write 2 0 9 write 3 0 10 write 5 0 //自己动手丰衣足食 49 write 701408733 0
subtask 3:
在图上bfs,找出1到n的路径,构造即可。
bfs:

#include<cstdio>
#include<queue>
using namespace std;
int G[105],to[250],nxt[250],sz=0,pre[105],st[105],sl=-1;
bool vis[205];
queue<int> Q;
inline void add(int u,int v){
to[++sz]=v;nxt[sz]=G[u];G[u]=sz;
to[++sz]=u;nxt[sz]=G[v];G[v]=sz;
}
int main(){
freopen("oldcomputer3.in","r",stdin);
freopen("bfs_res.out","w",stdout);
int n,m,i,u,v;
bool ok=0;
scanf("%d%d%d",&i,&n,&m);
while(m--){
scanf("%d%d",&u,&v);
add(u,v);
}
vis[1]=1;Q.push(1);
while(!Q.empty()&&!ok){
u=Q.front();Q.pop();
for(i=G[u];i;i=nxt[i])if(!vis[v=to[i]]){
pre[v]=u;
if(v==n){ok=1;break;}
vis[v]=1;
Q.push(v);
}
}
for(;pre[v];v=pre[v])st[++sl]=v;
puts("1");
while(sl>=0)printf("%d\n",st[sl--]);
return 0;
}
构造:(其实两个完全可以写在一起,懒得改了)

#include<cstdio>
int a[105];
int main(){
freopen("bfs_res.out","r",stdin);
freopen("oldcomputer3.out","w",stdout);
int i,x,m=0;
while(scanf("%d",&x)==1)a[++m]=x;
for(i=1;i<=m;++i)printf("node %d\nread %d a\nwrite a %d\n",a[i],a[i-1],a[i+1]);
return 0;
}
subtask 4:
从51~100号点往回跑最短路,可以发现1~50号点的距离都不超过3,这就提示我们可以根据距离递减来构造方案。
然而dfs构造的方案只能拿60%的分,周期太多了,于是我们乱搞一下:对于每个中转,记录下它之前有几个点,每个结点输出的时候贪心地选前面结点最少的中转先输出就AC了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int G[1005],to[4000],nxt[4000],sz=0,d[1005],n;
queue<int> Q;
struct opt{
int r,w,t;
opt(){}
opt(int r,int w,int t):r(r),w(w),t(t){}
};
vector<opt> V[1005];
inline bool cmp(opt a,opt b){return a.t<b.t;}
inline void add(int u,int v){
to[++sz]=v;nxt[sz]=G[u];G[u]=sz;
to[++sz]=u;nxt[sz]=G[v];G[v]=sz;
}
void dfs(int u,int fa,int t){
if(u>50&&u<=100){
V[u].push_back(opt(fa,0,t));
return;
}
int i,v;
for(i=G[u];i;i=nxt[i])if(d[v=to[i]]==d[u]-1&&V[v].size()<3){
V[u].push_back(opt(fa,v,t));
dfs(v,u,t+1);
return;
}
}
int main(){
freopen("oldcomputer4.in","r",stdin);
freopen("oldcomputer4.out","w",stdout);
int m,i,j,u,v;
scanf("%d%d%d",&i,&n,&m);
while(m--){
scanf("%d%d",&u,&v);
add(u,v);
}
memset(d,0x3f,sizeof(d));
for(i=51;i<=100;++i){
d[i]=0;
Q.push(i);
}
while(!Q.empty()){
u=Q.front();Q.pop();
for(i=G[u];i;i=nxt[i])if(d[v=to[i]]==0x3f3f3f3f){
d[v]=d[u]+1;
Q.push(v);
}
}
for(i=1;i<=50;++i)dfs(i,0,0);
for(i=1;i<=1000;++i)if(!V[i].empty()){
printf("node %d\n",i);
sort(V[i].begin(),V[i].end(),cmp);
for(j=0;j<V[i].size();++j)printf("read %d a\nwrite a %d\n",V[i][j].r,V[i][j].w);
}
return 0;
}
subtask 5:
这回要认真一点乱搞了。。。用$used_{u,t}$记下$u$在$t$时刻是不是有事做,那么$v$开始中转的时间$d_v$定为最小的$t$使得$t>d_u$且$used_{v,t}$,$used_{v,t+1}$均为$false$。跑10次$Dijkstra$即可。
事实证明邻接表存图60%,vector存图100%,实在不放心可以random_shuffle一下。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int d[105],pre[105];
bool used[105][25];
vector<int> G[105];
struct node{
int p,d;
node(){}
node(int p,int d):p(p),d(d){}
inline bool operator <(const node &b)const{return d>b.d;}
};
priority_queue<node> Q;
struct opt{
int r,w,t;
opt(){}
opt(int r,int w,int t):r(r),w(w),t(t){}
};
vector<opt> V[105];
inline bool cmp(opt a,opt b){return a.t<b.t;}
inline void dijkstra(int s,int t){
int i,u,v,dis=1,lst=0;
node h;
memset(d,0x3f,sizeof(d));
while(!Q.empty())Q.pop();
while(used[s][dis]||used[s][dis+1])++dis;
Q.push(node(s,d[s]=dis));
while(!Q.empty()){
h=Q.top();Q.pop();
if(d[u=h.p]!=h.d)continue;
if(u==t)break;
for(i=0;i<G[u].size();++i){
v=G[u][i];dis=d[u]+1;
while(used[v][dis]||used[v][dis+1])++dis;
if(dis<d[v]){
pre[v]=u;
Q.push(node(v,d[v]=dis));
}
}
}
v=t;
while(v!=s){
used[v][d[v]]=used[v][d[v]+1]=1;
V[v].push_back(opt(pre[v],lst,d[v]));
v=pre[lst=v];
}
used[s][d[s]]=used[s][d[s]]=1;
V[s].push_back(opt(0,lst,d[s]));
}
int main(){
freopen("oldcomputer5.in","r",stdin);
freopen("oldcomputer5.out","w",stdout);
int n,m,i,j,u,v;
scanf("%d%d%d",&i,&n,&m);
while(m--){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
for(i=1;i<=10;++i)dijkstra(i,101-i);
for(i=1;i<=100;++i)if(!V[i].empty()){
printf("node %d\n",i);
sort(V[i].begin(),V[i].end(),cmp);
for(j=0;j<V[i].size();++j)printf("read %d a\nwrite a %d\n",V[i][j].r,V[i][j].w);
}
return 0;
}
