题意:
你需要猜一个长度为n且仅由a和b组成的密文S,你可以向系统询问信息,每次询问输出一个非空串T,系统将告诉你(输入)S和T之间的编辑距离,你必须在n+2次询问内猜中密文S。S和T之间的编辑距离定义为:对S进行的最小操作数(对单个字符进行替换、插入或删除),使S=T ( 1 ≤ n ≤ 300 ) (1\le n\le300) (1≤n≤300)。
解法:
有意思的交互题。由于n不超过300,我们第一次询问串 T a = a a . . . a a , ∣ T a ∣ = 300 T_a=aa...aa,|T_a|=300 Ta=aa...aa,∣Ta∣=300,设系统返回的值为ax,则S中字符a的个数一定为300-ax;同理,第二次询问串 T b = b b . . . b b , ∣ T b ∣ = 300 T_b=bb...bb,|T_b|=300 Tb=bb...bb,∣Tb∣=300,设系统返回bx,则S中字符b的个数为300-bx,所以得到答案串长度n为600-ax-bx。于是分别用变量 c n t a 、 c n t b cnta、cntb cnta、cntb记录答案串中字符a和b的个数,并且初始化串 T 0 = a a . . . a a , ∣ T 0 ∣ = n T_0=aa...aa,|T_0|=n T0=aa...aa,∣T0∣=n。然后进行n-1次询问,第i次询问将 T 0 T_0 T0中的第i个字符改为b,并比较本次返回值ans和上一次询问的返回值las(初始化为cntb):若 a n s < l a s ans
复杂度: O ( n 2 ) O(n^2) O(n2)。
#include
#define ll long long
using namespace std;
string sets(char c,int len)
{
string ans="";
while(len--) ans+=c;
return ans;
}
int query(string s)
{
cout<<s<<endl;
int x; cin>>x;
if(!x) exit(0);
return x;
}
int main()
{
int cnta=300-query(sets('a',300));
int cntb=300-query(sets('b',300));
int n=cnta+cntb,las=cntb;
string s=sets('a',n);
for(int i=0;i<n-1;i++)
{
s[i]='b';
int ans=query(s);
if(ans<las) las=ans,cntb--;
else s[i]='a',cnta--;
}
if(cntb) s[n-1]='b';
query(s);
}
题意:
给一个n边形蛋糕,你需要切n-3次,切出n-2块三角形蛋糕,每次需要沿两端点将蛋糕切成两部分,其中的一块蛋糕必须为三角形并将其拿走。蛋糕的n个端点已有1~n的编号,最终的三角形蛋糕也有1~n-2的编号,按编号顺序给出每个三角形蛋糕的三个端点对应的编号,求:1. 原蛋糕的n个端点的顺序编号,顺时针或逆时针均可;2. 按切蛋糕的顺序,每次拿走的三角形蛋糕编号 ( 3 ≤ n ≤ 1 0 5 ) (3\le n\le 10^5) (3≤n≤105)。
解法:
设一块三角形蛋糕的三个端点为一个三元组{u,v,w},经观察可发现一个重要性质:与u、v同在一个三元组的w不会超过两个,且若这样的w只有一个,则端点u、v连成的线段一定在原蛋糕的边界线上;否则一定是蛋糕内部的分界线。
根据以上分析考虑两个问题。对于问题1,相当于要找到原蛋糕所有边界线,并形成一个圈,在圈上dfs顺序输出编号即可。对于问题2,将每一块三角形蛋糕看作结点,若两块蛋糕之间有一条分界线,即两个三元组中包含相同的u和v,则将两块蛋糕对应结点连边,问题即转换为该图的拓扑排序。
复杂度: O ( n ) O(n) O(n)。
#include
#define ll long long
using namespace std;
const int maxn=1e5+5;
struct node
{
int u,v;
node(int ux,int vx)
{ if(ux>vx) swap(ux,vx); u=ux,v=vx; }
};
int s,cnt,idx,deg[maxn],vis[maxn];
vector<node>id;
vector<int>e[2][maxn],v[maxn*3];
queue<int>q;
bool operator <(const node& x,const node& y)
{ return x.u<y.u||(x.u==y.u&&x.v<y.v); }
void link(int u,int v,int x)
{ e[x][u].push_back(v),e[x][v].push_back(u); }
void dfs(int u)
{
if(vis[u]) return;
vis[u]=true;
cout<<u<<" ";
for(int v:e[0][u]) dfs(v);
}
void bfs()
{
while(!q.empty())
{
int u=q.front();
q.pop(),vis[u]=true;
cout<<u<<" ";
for(int v:e[1][u])
{
if(vis[v]) continue;
if(--deg[v]<=1) q.push(v),vis[v]=true;
}
}
}
int main()
{
int t,n,x[3];
cin>>t;
while(t--)
{
cin>>n;
map<node,int>mp;
memset(deg,0,sizeof(deg));
for(int i=1;i<=n-2;i++)
{
for(int j=0;j<3;j++) cin>>x[j];
for(int j=0;j<3;j++)
{
node tmp=node(x[j],x[(j+1)%3]);
if(!mp.count(tmp))
id.push_back(tmp),idx=cnt++,mp[tmp]=idx;
idx=mp[tmp];
v[idx].push_back(i);
}
}
for(int i=1;i<=n;i++)
e[0][i].clear(),e[1][i].clear();
for(int i=0;i<(int)id.size();i++)
if(v[i].size()==1) link(id[i].u,id[i].v,0);
else
{
link(v[i][0],v[i][1],1);
deg[v[i][0]]++,deg[v[i][1]]++;
}
memset(vis,0,sizeof(vis)),dfs(1),puts("");
memset(vis,0,sizeof(vis));
for(int i=1;i<=n-2;i++)
if(deg[i]==1) q.push(i),vis[i]=true;
if(n==3) cout<<1;
bfs(),puts("");
for(int i=0;i<cnt;i++) v[i].clear();
cnt=0,id.clear();
}
}