P5207 [WC2019] 远古计算机 - 提交答案,图论
任务 \(1\)
周期 \(\le 200\)。
直接模拟即可。
node 1
read 0 a
write a 0
jmp 1
任务 \(2\)
周期 \(\le 4\)。
因为保证了 \(F_k\le 10^9\),所以 \(k\le 44\),所以直接把 \(\le 44\) 的斐波那契数算出来,然后 jmp
到正确的位置即可。
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
const int N=44;
int f[N+1];
int main(){
freopen("oldcomputer2.out","w",stdout);
cout<<"node 1\n";
cout<<"read 0 a\n";
cout<<"add a 4\n";
cout<<"jmp a\n";
f[0]=0,f[1]=1;
For(i,2,N) f[i]=f[i-1]+f[i-2];
For(i,0,N){
cout<<"write "<<f[i]<<" 0\n";
}
return 0;
}
任务 \(3\)
周期 \(\le 211\)。
我们求出 \(1\to 100\) 的最短路,按照这个最短路传输即可。
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
int a[]={100,80,98,56,37,36,50,40,54,13,7,1};
int main(){
freopen("oldcomputer3.out","w",stdout);
reverse(begin(a),end(a));
for(auto it=begin(a);it!=end(a);++it){
cout<<"node "<<*it<<"\n";
cout<<"read "<<(it==begin(a)?0:*prev(it))<<" a\n";
cout<<"write a "<<(it==prev(end(a))?0:*next(it))<<"\n";
}
return 0;
}
任务 \(4\)
周期 \(\le 7\)。
可以发现最短路不一定最优,因为执行的过程是多线程的,不能让一个点有过多的操作。我的方法比较笨,就是先求出来最短路再手动微调……
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
const int N=1e5+5;
int _,n,m;
vector<int> g[N];
int dis[N],pre[N];
string prog[N];
int plen[N];
int Splen(int u){
if(!u) return N;
int res=0;
while(u){
res=max(res,plen[u]);
u=pre[u];
}
return res;
}
int main(){
freopen("oldcomputer4.in","r",stdin);
freopen("oldcomputer4.out","w",stdout);
cin>>_>>n>>m;
For(i,1,m){
int u,v;cin>>u>>v;
g[u].push_back(v),g[v].push_back(u);
}
For(S,1,50){
memset(dis,0x3f,sizeof dis);
memset(pre,0,sizeof pre);
queue<int> q;
q.push(S),dis[S]=0;
while(!q.empty()){
int u=q.front();q.pop();
for(int v:g[u]){
if(dis[v]>dis[u]+1){
dis[v]=dis[u]+1;
pre[v]=u;
q.push(v);
}
}
}
int T=0,mdis=dis[51];
For(u,51,100) mdis=min(mdis,dis[u]);
For(u,51,100){
if(S==34&&dis[u]<=3){if(u!=68) T=u;}
else if(dis[u]==mdis&&Splen(u)<Splen(T)&&(S!=17||u!=93)&&(S!=19||u!=58)&&(S!=43||(u!=58&&u!=59))&&(S!=27||u!=59)) T=u;
}
cerr<<S<<":"<<dis[T]<<endl;
vector<int> pth;
while(T){
cerr<<T<<" ";
pth.push_back(T);
T=pre[T];
}
cerr<<endl;
reverse(pth.begin(),pth.end());
for(auto it=pth.begin();it!=pth.end();++it){
if(it==pth.begin()) prog[*it]+="read 0 a\n";
else prog[*it]+=string("read ")+to_string(*prev(it))+" a\n";
if(it==prev(pth.end())) prog[*it]+="write a 0\n";
else prog[*it]+=string("write a ")+to_string(*next(it))+"\n";
plen[*it]+=2;
}
}
For(i,1,n){
cout<<"node "<<i<<"\n";
cout<<prog[i];
}
return 0;
}
任务 \(5\)
周期 \(\le 21\)。
这下微调不出来了,哈哈。去学习了一下正确的写法:记录每个点在每个时间是否被占用,最短路转移的时候找到最小的未被占用的时间。
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
const int N=1005;
int _,n,m;
vector<int> g[N];
int dis[N],pre[N],used[N][N],ven[N];
vector<pair<int,string>> prog[N];
int main(){
freopen("oldcomputer5.in","r",stdin);
freopen("oldcomputer5.out","w",stdout);
cin>>_>>n>>m;
For(i,1,m){
int u,v;cin>>u>>v;
g[u].push_back(v),g[v].push_back(u);
}
For(i,1,10) used[i][0]=used[i][1]=1;
For(S,1,10){
memset(dis,0x3f,sizeof dis);
memset(pre,0,sizeof pre);
memset(ven,0,sizeof ven);
queue<int> q;
q.push(S),dis[S]=0,ven[S]=1;
while(!q.empty()){
int u=q.front();q.pop();
ven[u]=0;
for(int v:g[u]){
int w=dis[u]+1;
while(used[v][w]||used[v][w+1]) ++w;
if(w<dis[v]){
dis[v]=w,pre[v]=u;
if(!ven[v]) q.push(v),ven[v]=1;
}
}
}
int T=101-S;vector<int> pth;
int u=T;
while(u){
pth.push_back(u);
used[u][dis[u]]=used[u][dis[u]+1]=1;
u=pre[u];
}
reverse(pth.begin(),pth.end());
for(auto it=pth.begin();it!=pth.end();++it){
if(it==pth.begin()) prog[*it].push_back({dis[*it],"read 0 a\n"});
else prog[*it].push_back({dis[*it],string("read ")+to_string(*prev(it))+" a\n"});
if(it==prev(pth.end())) prog[*it].push_back({dis[*it],"write a 0\n"});
else prog[*it].push_back({dis[*it],string("write a ")+to_string(*next(it))+"\n"});
}
}
For(i,1,n){
cout<<"node "<<i<<"\n";
stable_sort(prog[i].begin(),prog[i].end());
for(const auto &x:prog[i]) cout<<x.second;
}
return 0;
}
Written by Alan_Zhao