好好的一道题。。被我错成这样。。唉。。。思路一开始就少注意到一个很重要的情况,给奇数偶数的问号插入字母时,需要先找到未出现过的、最优的字母
在需要填字母时
如a b c d ....w x y z
1 0 1 0 0 1 1 1
未用过的字母中
显然b比w更靠近边界,所以 优先选b 填在偶数位! 但是很重要的是,如果这时偶数位已经填满了! 就得填奇数位的!就是漏了这一点,又WA多次。。。
唉,分类还是总少考虑了情况
题目连接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=61977
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
char tm[100000+5];
int mark[28];
int que[100000+5];
int vis[100000+5];
int main()
{
int odd=0;
int even=0;
int i,k;
scanf("%s",tm+1);
scanf("%d",&k);
int len=strlen(1+tm);
int question=0;
int ok=0;
for (i=1;i<=len;i++)
{
if (tm[i]=='?')
{
question++;
que[++ok]=i;
if (i%2==1) odd++;
else
even++;
}
else
{
mark[tm[i]-'a'+1]=1;
}
}
int j;
int kind=0;
for (i=1;i<=26;i++)
{
if (mark[i])
kind++;
}
if (kind>=k)
{
if (question==0)
{
printf("%s\n",tm+1);
return 0;
}
else
{
for (i=1;i<=ok;i++)
{
if (que[i]%2==1&&vis[que[i]]==0)
{
tm[que[i]]='z';
vis[que[i]]=1;
}
if (que[i]%2==0&&vis[que[i]]==0)
{
tm[que[i]]='a';
vis[que[i]]=1;
}
}
printf("%s\n",tm+1);
return 0;
}
}
else
if (kind<k)
{
int need=k-kind;
if (need>odd+even)
{
printf("-1\n");
return 0;
}
// then need<= odd+even=question
while(need--)
{
int j1,j2;
for (j1=26;j1>=1;j1--)
{
if (mark[j1]==0) break;
}
for (j2=1;j2<=26;j2++)
{
if (mark[j2]==0) break;
}
int o_e;
if ((26-j1)<j2-1) o_e=0; //odd离两端较近,选之
else
o_e=1;
if (o_e==0&&odd||!even)
{
for (i=1;i<=ok&&odd;i++)
{
if (que[i]%2==1&&vis[que[i]]==0)
{
tm[que[i]]=j1-1+'a';
vis[que[i]]=1;
o_e=1;
odd--;
mark[j1]=1;
break;
}
}
}
else //去掉一个偶数min
{
for (i=1;i<=ok&&even;i++)
{
if (que[i]%2==0&&vis[que[i]]==0)
{
tm[que[i]]=j2-1+'a';
vis[que[i]]=1;
mark[j2]=1;
o_e=0;
even--;
// change++;
break;
}
}
}
}
if (odd)
{
for (i=1;i<=ok;i++)
{
if (que[i]%2==1&&vis[que[i]]==0)
{
tm[que[i]]='z';
vis[que[i]]=1;
odd--;
if (odd==0) break;
}
}
}
if (even)
{
for (i=1;i<=ok;i++)
{
if (que[i]%2==0&&vis[que[i]]==0)
{
tm[que[i]]='a';
vis[que[i]]=1;
even--;
if (even==0) break;
}
}
}
printf("%s\n",tm+1);
return 0;
}
return 0;
}