最近准备参加csp认证,做了几套题,放假闲的无聊写一下解析。
一般csp认证的第三道大题都是小模拟,主要考验我们做题者的阅读能力(最重要的!!!)以及敲代码的熟练程度,基本不会涉及到算法,适合我这种不会算法的小弱鸡。
本题不需要使用任何算法,对萌新非常友好!!!
问题信息:
问题背景
问题描述
输入输出格式
本题不需要使用任何算法,对萌新非常友好!!!
想做出这道题,我们需要先仔细读题,了解可用区间、节点以及任务应用之间的从属关系。简单来说,每个可用区间中包括了x个节点,每个节点内又包含了y个任务应用。其中节点中的任务应用在刚开始时都为0个,并且会随着程序的运行而更新。每个可用区间中的节点已经在输入中给出。
所以我们可以根据所属情况开两个数组,其中arpo[x][0]存储该区域内包含的节点数量,poatt[i][0]存储改节点内包含的任务数量。
int arpo[1005][1005]; //每个可用区间包含的节点
int poatt[1005][2005]; //每个节点包含的任务
首先我们读入每个节点所属的可用区间:
for(int i=1;i<=n;i++){
scanf("%d",&l[i]);
arpo[l[i]][0]++;
arpo[l[i]][arpo[l[i]][0]]=i;
}
然后可以根据输入格式读入需要处理的数据组数g
再读入一组的计算任务信息(同志们可以根据自己的喜好选择是读完所有组的信息后再对数据进行处理,也可以边读入边进行处理。个人习惯边读入边处理数据。)
int f,a,na,pa,paa,paar;
scanf("%d%d%d%d%d%d",&f,&a,&na,&pa,&paa,&paar);
由题意可得读入f组相同的信息与读入相同的信息f次本质相同,所以建立一个for1~f的循环进行数据的处理。
在处理每个数据时,我们需要设置这几个量来存储基本信息,其中ar[]表示可以选择的可用区间,po0[]表示paar等于0时可以选择的节点,po1[]表示paar等于1时可以选择的节点,arnum表示可用区间数量(直接存在ar[0]里面也可,但是容易写着写着就乱了),ponum同arnum。想只拿部分分的同志们可以选择只开一个数组存可用节点
int ar[1005]={0},po0[1005][2]={0},po1[1005][2]={0},arnum=0,ponum=0;
本题在输入上对我们有一个误导,题干中先读入na再读入pa,如果我们按照题干所给的数据顺序来进行数据处理的话,可能会造成可用区间的遗漏或是过量。因此我先处理pa(计算任务亲和性要求)
if(pa==0){
for(int k=1;k<=m;k++) ar[k]=k;
arnum=m;
}
else{
for(int k=1;k<=m;k++){
if(findatt(k,pa)){
arnum++;
ar[arnum]=k;
}
}
}
findatt函数来判断该可用区间内是否含有编号为pa的任务
bool findatt(int ar,int pa){
for(int i=1;i<=arpo[ar][0];i++){ //含节点量
for(int j=1;j<=arpo[ar][i];j++){ //节点编号
for(int k=1;k<=poatt[arpo[ar][i]][0];k++){ //含任务量
if(poatt[arpo[ar][i]][k]==pa) return 1;
}
}
}
return 0;
}
此时我们得到了可用区间ar[],但还需要对ar[]进行处理,na!=0时需要找出ar[]中编号为na的区间,na==0时则不需要对ar[]进行进一步处理
if(na!=0){
int flag=0;
for(int k=1;k<=arnum;k++){
if(ar[k]==na) flag=1;
ar[k]=0;
}
if(flag){
arnum=1;
ar[1]=na;
}
else arnum=0;
}
由于已经找到了可用区间,那么可用节点也可以推出(po0为paar==0时的节点,po1为paar==1时的节点)
for(int k=1;k<=arnum;k++){
for(int p=1;p<=arpo[ar[k]][0];p++){
ponum++;
po0[ponum][0]=arpo[ar[k]][p];
po0[ponum][1]=poatt[arpo[ar[k]][p]][0];
po1[ponum][0]=arpo[ar[k]][p];
po1[ponum][1]=poatt[arpo[ar[k]][p]][0];
}
}
再对paa进行处理
if(paa!=0){
for(int k=1;k<=ponum;k++){
if(!findatt1(po1[k][0],paa)) po1[k][0]=0;
}
}
bool findatt1(int po,int paa){
for(int i=1;i<=poatt[po][0];i++){
if(poatt[po][i]==paa) return 0;
}
return 1;
}
现在对数据的处理已经完成了,接下来可以进行输出,题干中对输出的节点做了要求
for(int k=1;k<=ponum;k++){
if((po0[k][0]!=0&&po0[k][1]<attnum)||(po0[k][0]<pri&&po0[k][1]==attnum)){
pri=po0[k][0];
attnum=po0[k][1];
flag=1;
}
}
if(flag){
printf("%d ",pri);
poatt[pri][0]++;
poatt[pri][poatt[pri][0]]=a;
}
如果paar==0&&没有输出的话,再检查一遍如果不做paa的话能否输出
if(!flag&&!paar){
for(int k=1;k<=ponum;k++){
if(po0[k][0]!=0&&(po0[k][1]<attnum||(po0[k][0]<pri&&po0[k][1]==attnum))){
pri=po0[k][0];
attnum=po0[k][1];
flag=1;
}
}
if(flag){
printf("%d ",pri);
poatt[pri][0]++;
poatt[pri][poatt[pri][0]]=a;
}
}
总代码(输出可以单写一个函数,这样能少敲几十行,写的时候没注意现在懒得改了)
#include<bits/stdc++.h>
using namespace std;
int n,m,g,arpo[1005][1005],poatt[1005][2005],l[1005];
bool findatt(int ar,int pa){
for(int i=1;i<=arpo[ar][0];i++){ //含节点量
for(int j=1;j<=arpo[ar][i];j++){ //节点编号
for(int k=1;k<=poatt[arpo[ar][i]][0];k++){ //含任务量
if(poatt[arpo[ar][i]][k]==pa) return 1;
}
}
}
return 0;
}
bool findatt1(int po,int paa){
for(int i=1;i<=poatt[po][0];i++){
if(poatt[po][i]==paa) return 0;
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&l[i]);
arpo[l[i]][0]++;
arpo[l[i]][arpo[l[i]][0]]=i;
}
scanf("%d",&g);
for(int i=1;i<=g;i++){
int f,a,na,pa,paa,paar;
scanf("%d%d%d%d%d%d",&f,&a,&na,&pa,&paa,&paar);
for(int j=1;j<=f;j++){
int ar[1005]={0},po0[1005][2]={0},po1[1005][2]={0},arnum=0,ponum=0;
if(pa==0){
for(int k=1;k<=m;k++) ar[k]=k;
arnum=m;
}
else{
for(int k=1;k<=m;k++){
if(findatt(k,pa)){
arnum++;
ar[arnum]=k;
}
}
}
if(na!=0){
int flag=0;
for(int k=1;k<=arnum;k++){
if(ar[k]==na) flag=1;
ar[k]=0;
}
if(flag){
arnum=1;
ar[1]=na;
}
else arnum=0;
}
for(int k=1;k<=arnum;k++){
for(int p=1;p<=arpo[ar[k]][0];p++){
ponum++;
po0[ponum][0]=arpo[ar[k]][p];
po0[ponum][1]=poatt[arpo[ar[k]][p]][0];
po1[ponum][0]=arpo[ar[k]][p];
po1[ponum][1]=poatt[arpo[ar[k]][p]][0];
}
}
bool flag=0;
int attnum=1005,pri=0;
if(paa!=0){
for(int k=1;k<=ponum;k++){
if(!findatt1(po1[k][0],paa)) po1[k][0]=0;
}
}
else{
for(int k=1;k<=ponum;k++){
if((po0[k][0]!=0&&po0[k][1]<attnum)||(po0[k][0]<pri&&po0[k][1]==attnum)){
pri=po0[k][0];
attnum=po0[k][1];
flag=1;
}
}
if(flag){
printf("%d ",pri);
poatt[pri][0]++;
poatt[pri][poatt[pri][0]]=a;
}
}
if(!flag){
for(int k=1;k<=ponum;k++){
if(po1[k][0]!=0&&(po1[k][1]<attnum||(po1[k][0]<pri&&po1[k][1]==attnum))){
pri=po1[k][0];
attnum=po1[k][1];
flag=1;
}
}
if(flag){
printf("%d ",pri);
poatt[pri][0]++;
poatt[pri][poatt[pri][0]]=a;
}
}
if(!flag&&!paar){
for(int k=1;k<=ponum;k++){
if(po0[k][0]!=0&&(po0[k][1]<attnum||(po0[k][0]<pri&&po0[k][1]==attnum))){
pri=po0[k][0];
attnum=po0[k][1];
flag=1;
}
}
if(flag){
printf("%d ",pri);
poatt[pri][0]++;
poatt[pri][poatt[pri][0]]=a;
}
}
if(!flag) printf("0 ");
}
printf("\n");
}
return 0;
}