渣诚拖了好久的解题报告,于是我还是自行解决吧……
A. Arthur的收藏夹
B. Chem is A Brand New Try!
E. RPS GAMES
三道上机原题,没啥讲的,见上机题解。
C. 链表的中间节点
陈题,题干里Hint的提示足够简洁明了,唯一要注意的是分割字符串的方法,下面的标程给出了两种方式(手动分割,以及strtok函数);还有,其实没必要把字符转化成数字。
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
struct LinkList
{
char data[5];
LinkList *next;
};
char str[1005];
void CreateList(LinkList *&L)
{
LinkList *s,*r;
L=(LinkList *)malloc(sizeof(LinkList));
r=L;
int f=0,l=strlen(str);
for(int i=0; i<l; ++i)
if(str[i+1]==' '||i==l-1)
{
++i;
s=(LinkList *)malloc(sizeof(LinkList));
for(int j=0; j<i-f; j++)
s->data[j]=str[j+f];
s->data[i-f]='\0';
r->next=s;
r=s;
f=i+1;
}
r->next=NULL;
}
void MiddleOfList(LinkList *&L)
{
LinkList *p1=L->next,*p2=L->next;
while(p2->next!=NULL)
{
p2=p2->next->next;
p1=p1->next;
}
printf("%s\n",p1->data);
}
void DestroyList(LinkList *&L)
{
LinkList *pre=L,*p=L->next;
while(p)
{
free(pre);
pre=p;
p=pre->next;
}
free(pre);
}
int main()
{
int t;
scanf("%d",&t);
getchar();
while(t--)
{
gets(str);
LinkList *L;
CreateList(L);
MiddleOfList(L);
DestroyList(L);
}
}
#include<cstdio>
#include<cstring>
#include<string>
#include<list>
using namespace std;
char str[1005];
list<string> data;
list<string>::iterator it,mid;
int main()
{
int t;
scanf("%d",&t);
getchar();
while(t--)
{
gets(str);
char *sub=strtok(str," ");
while(sub)
{
data.push_back(sub);
sub=strtok(NULL," ");
}
it=data.begin();
mid=it++;
while(it!=data.end())
{
advance(it,2);
++mid;
}
printf("%s\n",(*mid).c_str());
data.clear();
}
}
D. Who Should I Accompany?(Ⅱ)
双向约瑟夫,加点条件罢了,双链表纯模拟。
#include<cstdio>
#include<cstdlib>
using namespace std;
struct DLinkList
{
int data;
DLinkList *prior,*next;
};
void CreateList(DLinkList *&L,int n)
{
DLinkList *s,*r;
L=(DLinkList *)malloc(sizeof(DLinkList));
r=L;
for(int i=1; i<=n; ++i)
{
s=(DLinkList *)malloc(sizeof(DLinkList));
s->data=i;
r->next=s;
s->prior=r;
r=s;
}
r->next=L->next;
L->next->prior=r;
}
void Josephus(DLinkList *&L,int k)
{
DLinkList *p=L->next->prior,*q;
int cnt=0;
while(p->next!=p)
{
if(cnt&1)
{
for(int i=1; i<k+cnt; ++i)
p=p->prior;
q=p->prior;
p->prior=q->prior;
q->prior->next=p;
p=p->prior;
}
else
{
for(int i=1; i<k+cnt; ++i)
p=p->next;
q=p->next;
p->next=q->next;
q->next->prior=p;
p=p->next;
}
free(q);
++cnt;
}
printf("%d\n",p->data);
free(p);
free(L);
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
DLinkList *L;
CreateList(L,n);
Josephus(L,k);
}
}
#include<cstdio>
#include<list>
using namespace std;
list<int> data;
list<int>::iterator p,q;
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
for(int i=1; i<=n; ++i)
data.push_back(i);
p=data.begin();
int cnt=0;
while(cnt!=n-1)
{
if(cnt&1)
{
for(int i=1; i<k+cnt; ++i)
{
if(p==data.begin())
p=data.end();
--p;
}
q=p++;
if(p==data.end())
p=data.begin();
}
else
{
for(int i=1; i<k+cnt; ++i)
{
++p;
if(p==data.end())
p=data.begin();
}
q=p;
if(p==data.begin())
p=data.end();
--p;
}
data.erase(q);
++cnt;
}
printf("%d\n",*p);
data.clear();
}
}
F. 大富翁
这道题不太好搞,边界处理有点恶心。双链表不用说了,我的做法是先往一边数B+C次,然后再往回数C次,这样可以回避一部分边界情况。
#include<cstdio>
#include<cstdlib>
using namespace std;
struct DLinkList
{
int data;
DLinkList *prior,*next;
};
void CreateList(DLinkList *&L,int n)
{
DLinkList *s,*r;
L=(DLinkList *)malloc(sizeof(DLinkList));
r=L;
for(int i=1; i<=n; i++)
{
s=(DLinkList *)malloc(sizeof(DLinkList));
s->data=i;
r->next=s;
s->prior=r;
r=s;
}
r->next=NULL;
}
void DestroyList(DLinkList *&L)
{
DLinkList *pre=L,*p=L->next;
while(p!=NULL)
{
free(pre);
pre=p;
p=pre->next;
}
free(pre);
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
DLinkList *L,*p,*q;
scanf("%d%d",&n,&m);
CreateList(L,n);
p=L->next;
while(m--)
{
int a,b,c;
scanf("%d",&a);
if(a!=0)
{
scanf("%d%d",&b,&c);
if(a==1)
{
for(int i=0; i<b+c; ++i)
{
if(p->next==NULL)
break;
p=p->next;
}
for(int i=0; i<c; ++i)
{
if(p==L)
{
p=p->next;
break;
}
p->prior->next=p->next;
if(p->next!=NULL)
p->next->prior=p->prior;
q=p;
p=p->prior;
free(q);
}
}
else if(a==-1)
{
for(int i=0; i<b+c; ++i)
{
if(p->prior==L)
break;
p=p->prior;
}
for(int i=0; i<c; ++i)
{
if(p==NULL)
{
p=L;
while(p->next!=NULL)
p=p->next;
break;
}
p->prior->next=p->next;
if(p->next!=NULL)
p->next->prior=p->prior;
q=p;
p=p->next;
free(q);
}
}
}
}
p=L->next;
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
putchar('\n');
DestroyList(L);
}
}
#include<cstdio>
#include<list>
using namespace std;
list<int> data;
list<int>::iterator p,q;
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<=n; ++i)
data.push_back(i);
p=data.begin();
++p;
while(m--)
{
int a,b,c;
scanf("%d",&a);
if(a==0)
continue;
scanf("%d%d",&b,&c);
switch(a)
{
case 1:
for(int i=0; i<b+c; ++i)
{
++p;
if(p==data.end())
{
--p;
break;
}
}
for(int i=0; i<c; ++i)
{
if(p==data.begin())
{
++p;
break;
}
q=p;
--p;
data.erase(q);
}
break;
case -1:
for(int i=0; i<b+c; ++i)
{
--p;
if(p==data.begin())
{
++p;
break;
}
}
for(int i=0; i<c; ++i)
{
if(p==data.end())
{
--p;
break;
}
q=p;
++p;
data.erase(q);
}
break;
}
}
for(p=data.begin(),++p; p!=data.end(); ++p)
printf("%d ",*p);
putchar('\n');
data.clear();
}
}
G. Thor's Play
栈的纯模拟,无坑点,不说了。
#include<cstdio>
using namespace std;
const int MAXN=10005;
int stack[MAXN],size;
int main()
{
int n,m,k;
char str[10];
while(~scanf("%d%d",&n,&m))
{
size=0;
while(m--)
{
scanf("%s",str);
bool flag=true;
switch(str[0])
{
case 'P':
scanf("%d",&k);
if(size==n)
flag=false;
else
stack[++size]=k;
break;
case 'R':
if(size==0)
flag=false;
else
--size;
break;
case 'G':
scanf("%d",&k);
while(size>0&&stack[size]!=k)
--size;
if(size==0)
flag=false;
else
--size;
break;
}
puts(flag?"SUCCEED":"ERROR");
}
for(int i=size; i>=1; --i)
printf("%d ",stack[i]);
putchar('\n');
}
}
#include<cstdio>
#include<stack>
using namespace std;
stack<int> s;
int main()
{
int n,m,k;
char str[10];
while(~scanf("%d%d",&n,&m))
{
while(m--)
{
scanf("%s",str);
bool flag=true;
switch(str[0])
{
case 'P':
scanf("%d",&k);
if(s.size()==n)
flag=false;
else
s.push(k);
break;
case 'R':
if(s.empty())
flag=false;
else
s.pop();
break;
case 'G':
scanf("%d",&k);
while(!s.empty()&&s.top()!=k)
s.pop();
if(s.empty())
flag=false;
else
s.pop();
break;
}
puts(flag?"SUCCEED":"ERROR");
}
while(!s.empty())
{
printf("%d ",s.top());
s.pop();
}
putchar('\n');
}
}
H. 优雅的XML
SZM大神出的题,我在13年成都现场赛上做过一道很相似的题(HDU4782),当时没搞出来。主要是要考虑到一切情况,边界条件众多,小心使得万里船。我的代码很难看。
#include<cstdio>
using namespace std;
int main()
{
int len=0,cnt=0;
char buf[4096];
while((buf[len]=getchar())!=EOF)
++len;
for(int i=0; i<len; ++i)
{
if(buf[i]==' '||buf[i]=='\n'||buf[i]=='\t')
continue;
if(buf[i]=='<')
{
int j=i+1;
while(buf[j]==' '||buf[j]=='\n'||buf[j]=='\t')
++j;
if(buf[j]=='/')
--cnt;
for(int k=0; k<cnt; ++k)
putchar('\t');
if(buf[j]!='/')
++cnt;
putchar(buf[i++]);
int quo=0;
while(buf[i]==' '||buf[i]=='\n'||buf[i]=='\t')
++i;
if(buf[i]=='/')
{
putchar(buf[i++]);
while(buf[i]==' '||buf[i]=='\n'||buf[i]=='\t')
++i;
}
while(buf[i]!='>'&&buf[i]!=' '&&buf[i]!='\n'&&buf[i]!='\t')
putchar(buf[i++]);
while(buf[i]==' '||buf[i]=='\n'||buf[i]=='\t')
++i;
if(buf[i]!='>')
{
putchar(' ');
for(; buf[i]!='>'; ++i)
{
if(!(quo&1)&&(buf[i]==' '||buf[i]=='\n'||buf[i]=='\t'))
continue;
putchar(buf[i]);
if(buf[i]=='\"'&&buf[i-1]!='\\')
{
++quo;
if(!(quo&1))
{
++i;
while(buf[i]==' '||buf[i]=='\n'||buf[i]=='\t')
++i;
if(buf[i]=='>')
break;
--i;
putchar(' ');
}
}
}
}
putchar(buf[i]);
j=i-1;
while(buf[j]==' '||buf[j]=='\n'||buf[j]=='\t')
--j;
if(buf[j]=='/')
--cnt;
putchar('\n');
}
}
}
送一组数据,能过这一组应该就没问题了。输入为:
< html xmlns="http://www.w3school.com.cn">< head
> < link href="/static/css/oj3rd.css" rel = "stylesheet" type="text/css" / >
< / head > < body > < div id = "header " class="clearfix" > <a href= "/problem/group/85/create/" >
</a>
< / div >
</body></ html>
输出效果为:
<html xmlns="http://www.w3school.com.cn">
<head>
<link href="/static/css/oj3rd.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header " class="clearfix">
<a href="/problem/group/85/create/">
</a>
</div>
</body>
</html>
解题报告真的不好写也懒得写……看看标程应该也能懂的吧。