#include<bits/stdc++.h>
using namespace std;
int n;//物理块号数
int len,op;//进程数
int a[100];//存储进程执行的先后顺序;
int res[100][100];//存放进程执行的结果数组
int optfind[100],optflag[100];
int lruflag[1000];
int nru_value[100],nru_r[100],nru_m[100];
void print(){
printf("运行结果图示为:\n");
for(int i=1;i<=len;i++) printf("%2d",a[i]);
printf("\n");
for(int j=1;j<=n;j++){
for(int i=1;i<=len;i++){
printf("%2d",res[i][j]);
}
printf("\n");
}
}
void fifo()
{
for(int i=1;i<=len;i++)
{
if(i!=1){
int temp=res[i-1][n];
for(int j=2;j<=n;j++){
if(res[i-1][j-1]!=-1) res[i][j]=res[i-1][j-1];
}
if(temp!=-1) res[i][1]=temp;
}else{
res[1][1]=a[1];continue;
}
int flag=0;
for(int j=1;j<=n;j++){
if(res[i][j]==a[i]) flag=j;
}
if(flag!=0){
int temp=res[i][flag];
for(int j=2;j<=flag;j++){
res[i][j]=res[i][j-1];
}
res[i][1]=temp;
}else{
for(int j=2;j<=n;j++){
if(res[i-1][j-1]!=-1) res[i][j]=res[i-1][j-1];
}
res[i][1]=a[i];
}
}
print();
}
void opt(){
for(int i=1;i<=len;i++)
{
if(i<=3){
for(int j=1;j<=i;j++){
if(j==i) res[i][j]=a[i];
else res[i][j]=res[i-1][j];
}
continue;
}
for(int j=1;j<=n;j++) res[i][j]=res[i-1][j];
int flag=0;
for(int j=1;j<=n;j++){
if(res[i][j]==a[i]) flag=1;
}
if(flag==1) continue;
for(int j=1;j<=n;j++){
optfind[j]=999;//初始化opt的寻找数组
optflag[j]=0;
}
for(int j=1;j<=n;j++){
for(int k=i;k<=len;k++){
if(res[i-1][j]==a[k]){
optfind[j]=k;
optflag[j]=1;
}
if(optflag[j]==1) break;
}
}
int minnum=optfind[1],minflag=1;
for(int j=2;j<=n;j++){
minnum=min(minnum,optfind[j]);
minflag=j;
}
res[i][minflag]=a[i];
}
print();
}
void nru(){//最久未使用,同lru
for(int i=1;i<=len;i++)
{
if(i<=3){
for(int j=1;j<=i;j++){
if(j==i) res[i][j]=a[i];
else res[i][j]=res[i-1][j];
}
continue;
}
for(int j=1;j<=n;j++) res[i][j]=res[i-1][j];
int flag=0;
for(int j=1;j<=n;j++){
if(res[i][j]==a[i]) flag=1;
}
if(flag==1) continue;
int cnt=0,wantnum;
for(int j=0;j<=100;j++) lruflag[j]=0;
for(int k=i-1;k>=1;k--){
if(lruflag[a[k]]==0){
cnt++;
lruflag[a[k]]=1;
}
if(cnt==n){
wantnum=a[k];break;
}
}
for(int j=1;j<=n;j++){
if(res[i][j]==wantnum){
res[i][j]=a[i];break;
}
}
}
print();
}
void lru(){
for(int i=1;i<=len;i++)
{
if(i<=3){
for(int j=1;j<=i;j++){
if(j==i) res[i][j]=a[i];
else res[i][j]=res[i-1][j];
}
continue;
}
for(int j=1;j<=n;j++) res[i][j]=res[i-1][j];
int flag=0;
for(int j=1;j<=n;j++){
if(res[i][j]==a[i]) flag=1;
}
if(flag==1) continue;
int cnt=0,wantnum;
for(int j=0;j<=100;j++) lruflag[j]=0;
for(int k=i-1;k>=1;k--){
if(lruflag[a[k]]==0){
cnt++;
lruflag[a[k]]=1;
}
if(cnt==n){
wantnum=a[k];break;
}
}
for(int j=1;j<=n;j++){
if(res[i][j]==wantnum){
res[i][j]=a[i];break;
}
}
}
print();
}
int main()
{
// 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
printf("请输入物理块号数n:");
scanf("%d",&n);
printf("请输入进程的数量len:");
scanf("%d",&len);
for(int i=0;i<=len;i++)
for(int j=0;j<=n;j++) res[i][j]=-1;
printf("请输入个数字代表即将分配的进程顺序:\n");
for(int i=1;i<=len;i++) scanf("%d",&a[i]);
printf("请选择采用什么页面置换算法:\n1.OPT\n2.NRU\n3.FIFO\n4.LRU\n");
scanf("%d",&op);
switch(op){
case 1:{
opt();
break;
}
case 2:{
nru();
break;
}
case 3:{
fifo();
break;
}
case 4:{
lru();
break;
}
default:printf("输入错误不合规范!\n");
}
}