小Hi小Ho的惊天大作战:扫雷·一

真题描述(友情提示题目太长)

输入

每个测试点(输入文件)存在多组测试数据。

每个测试点的第一行为一个整数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

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值