输入
每个测试点(输入文件)存在多组测试数据。
每个测试点的第一行为一个整数Task,表示测试数据的组数。
在一组测试数据中:
第1行为1个整数N,表示迷宫的宽度。
第2行为N个整数A_1 … A_N,依次表示迷宫第二行的N个格子里标注的数字。
对于100%的数据,满足1<=N<=10^5, 0<=a_i<=3.<>
对于100%的数据,满足符合数据描述的地图一定存在。
输出
对于每组测试数据,输出2行,其中第一行先输出一定为地雷的格子的数量,然后按照从小到大的顺序输出所有一定为地雷的格子的位置,第二行先输出一定不为地雷的格子的数量,按照从小到大的顺序输出所有一定不为地雷的格子的位置。
Sample Input
2
3
1 1 1
10
1 2 1 2 2 3 2 2 2 2
Sample Output
1 2
2 1 3
7 1 3 5 6 7 9 10
3 2 4 8
思路
我的思路有些暴力,大致就是对于首位的数字进行分类讨论。
其余的都是一些dp的基本思想。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100005;
int T,n,o[MAXN],x[MAXN];
int l1,l2,b[MAXN],c[MAXN];
int ans[5][MAXN],s;
int main()
{
scanf("%d",&T);
while(T--)
{
for(int i=0;i<=n+1;i++)
{
for(int j=0;j<=s+1;j++)
ans[j][i]=0;
o[i]=x[i]=b[i]=c[i]=0;
}
l1=l2=s=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&x[i]);
if(n==1)
{
if(x[1])printf("1 1\n0\n");
else printf("0\n1 1\n");
continue;
}
else
{
if(x[1]==0)
{
s++;
for(int i=3;i<=n;i++)
o[i]=x[i-1]-o[i-1]-o[i-2];
for(int i=1;i<=n;i++)
ans[s][i]=o[i];
}
if(x[1]==1)
{
o[1]=1;int you=0;
for(int i=3;i<=n;i++)
{
o[i]=x[i-1]-o[i-1]-o[i-2];
if(o[i]>1||o[i]<0){you=1;break;}
}
o[0]=o[n+1]=0;
if(!you&&x[n]==o[n-1]+o[n])
{
s++;
for(int i=1;i<=n;i++)
ans[s][i]=o[i];
}
for(int i=1;i<=n;i++)
o[i]=0;
o[2]=1;you=0;
for(int i=3;i<=n;i++)
{
o[i]=x[i-1]-o[i-1]-o[i-2];
if(o[i]>1||o[i]<0){you=1;break;}
}
if(!you&&x[n]==o[n-1]+o[n])
{
s++;
for(int i=1;i<n+1;i++)
ans[s][i]=o[i];
}
}
if(x[1]==2)
{
s++;
o[1]=o[2]=1;
for(int i=3;i<=n;i++)
o[i]=x[i-1]-o[i-1]-o[i-2];
for(int i=1;i<=n;i++)
ans[s][i]=o[i];
}
}
if(s==1)
{
for(int i=1;i<=n;i++)
{
if(ans[1][i])b[++l1]=i;
else c[++l2]=i;
}
}
else
{
for(int i=1;i<=n;i++)
{
if(ans[1][i]&&ans[2][i])
b[++l1]=i;
if(!ans[1][i]&&!ans[2][i])
c[++l2]=i;
}
}
//printf("%d\n",s);
printf("%d",l1);
for(int i=1;i<=l1;i++)
printf(" %d",b[i]);
printf("\n%d",l2);
for(int i=1;i<=l2;i++)
printf(" %d",c[i]);
puts("");
}
return 0;
}
/*
5
1 1 1 1 1
1 0 0 1 0
0 1 0 0 1
*/