hit or miss 解题报告
方法一:
#include<iostream>
using namespace std;
const int maxn=10010;
const int maxm=15;
int i,j,k,m,n;
int sum;
int head[maxm],tail[maxm],counter[maxm];
int f[maxm][maxn];
int check(int cn)
{
int ci;
for(ci=1;ci<cn;++ci)if(tail[ci]>=head[ci])return 0;
int ck;
ck=counter[cn];
for(ci=head[cn];ci<=tail[cn];++ci)
{
++ck;
if(ck==14)ck=1;
if(f[cn][ci]==ck)return 0;
}
sum=-1;
return 0;
}
int main()
{
cin>>n;
int ni;
for(ni=1;ni<=n;++ni)
{
cin>>m;
for(i=1;i<=52;++i) cin>>f[1][i];
for(i=1;i<=m;++i)
{
counter[i]=0;
head[i]=1;
tail[i]=0;
}
tail[1]=52;
sum=52;
check(1);
while(sum>0)
{
for(i=1;i<=m;++i)
{
// cout<<i<<":"<<tail[i]-head[i]+1<<endl;
if(sum<=0)break;
if(head[i]>tail[i]) continue;
++counter[i];
if(counter[i]==14)counter[i]=1;
if(f[i][head[i]]!=counter[i])
{
++tail[i];
f[i][tail[i]]=f[i][head[i]];
++head[i];
continue;
}
if(i==m)
{
--sum;
++head[i];
if((tail[i]-head[i]+1>0)&&((tail[i]-head[i]+1)%13==0))check(i);
continue;
}
j=i+1;
++tail[j];
f[j][tail[j]]=f[i][head[i]];
if((tail[j]-head[j]+1>0)&&((tail[j]-head[j]+1)%13==0))check(j);
++head[i];
if((tail[i]-head[i]+1>0)&&((tail[i]-head[i]+1)%13==0))check(i);
}
}
if(sum==-1)
{
cout<<"Case "<<ni<<": unwinnable"<<endl;
continue;
}
cout<<"Case "<<ni<<":";
for(i=1;i<=m;++i)cout<<" "<<f[i][tail[i]];
cout<<endl;
}
return 0;
}
//这个判定条件比较难以理解,但这种用数组简明的模拟队列在效率上会有很大的提高,而且该代码在逻辑上非常明确在许多分支的判定语句上都做了相应的化简。
方法二:
#include <iostream>
#include <queue>
using namespace std;
int const per_max = 22;
int ans[per_max]={0};
int main() {
int t;
cin>>t;
for (int id = 1;id<=t;id++) {
int m;
cin>>m;
queue<int> person[22];
int tot[per_max] = {0};
int count[per_max]={0};
for (int i=0;i<52;i++) {
int tmp;
cin>>tmp;
person[0].push(tmp);
}
int i = 0;
int sum = 52;
int win = 0;
while(sum) {
if (person[i].empty()) {
i++;
if (i==m) i=0;
continue;
}
tot[i]++;
count[i]++;
if(count[i]==14) count[i] = 1;
if(count[i] == person[i].front()) {
ans[i] = person[i].front();
person[i+1].push(person[i].front());
tot[i]=0;
person[i].pop();
if (i==m-1)
sum--;
} else {
person[i].push(person[i].front());
person[i].pop();
}
if(tot[i]>int(person[i].size()*13)) break;
i++;
if (i==m) i=0;
}
cout<<"Case " <<id<<": ";
if (sum!=0) {
cout<<"unwinnable";
} else {
for (int i=0;i<m-1;i++) cout<<ans[i]<<" ";
cout<<ans[m-1];
}
cout<<endl;
}
}
/*此方法容易直观,运用stl库的良好封装性,所以代码量较少,但可能本人水平有限一直不知道怎么在调试过程中查看stl数据类型中相应的值的量。此题的判定终止条件是队列的长度乘以13对应了极限的情况即每位数均与1-13个数比较,较方法一更易于理解*/