HDU 5386 思维

HDU 5386

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5386

题意:

给两个矩阵ST,给一些操作,操作可以把一行或一列全变成一个数字。问操作顺序。SPJ

思路:

思维题,因为一定有解,所以反着来只看目标矩阵,每次找满足条件的行或列,满足的条件是除了被访问过的点,其余点都相同,然后存不存在这样的操作,(注意,这里WA了无数)如果存在,则把该行或该列设置为访问过。

题解或者标程有错,如果出现极限数据如

2

3

1

3

4

4

1

3

2

2

2

3

4

4

4

4

复杂度会变成o(m!)

只有每次都只遍历图然后查询是否有类似操作的On^3+m)才是正解哦~

Debug等级又升,调了一个下午加半个晚上。

源码:

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <algorithm>

#include <iostream>

#include <stack>

#include <vector>

using namespace std;

const int MAXN = 110;

int a[MAXN][MAXN], n, m;

int v[505];

vector<int>x[MAXN], y[MAXN];

vector<int>::iterator it;

int ans[505];

int visr[MAXN], visc[MAXN];

int vis[505];

void output_a()

{

    printf("a\n");

    for(int i = 1 ; i <= n ; i++){

        for(int j = 1 ; j <= n ; j++)

            printf("%d ", a[i][j]);

        printf("\n");

    }

    printf("a\n");

}

int main()

{

//    freopen("1007.in", "r", stdin);

//    freopen("1007.out", "w", stdout);

    int t;

    scanf("%d", &t);

    while(t--){

        scanf("%d%d", &n, &m);

        memset(a, 0, sizeof(a));

        for(int i = 1 ; i <= n ; i++)

            for(int j = 1 ; j <= n ; j++)

                scanf("%d", &a[i][j]);

        for(int i = 1 ; i <= n ; i++)

            for(int j = 1 ; j <= n ; j++)

                scanf("%d", &a[i][j]);

        for(int i = 1 ; i <= n ; i++)

            x[i].clear(), y[i].clear();

        for(int i = 1 ; i <= m ; i++){

            int t1, t2;

            char str[5];

            scanf("%s", str);

            scanf("%d%d", &t1, &t2);

            v[i] = t2;

//            printf("t1 = %d, t2 = %d, op = %c, i = %d\n", t1, t2, str[0] == 'H' ? 'x' : 'y', i);

            if(str[0] == 'H')

                x[t1].push_back(i);

            else

                y[t1].push_back(i);

        }

        memset(vis, 0, sizeof(vis));

        memset(visr, 0, sizeof(visr));

        memset(visc, 0, sizeof(visc));

        int cnt = 1;

        for(int i = 0; i <= 2*n ; i++){

            int totalok = 0;

//            output_a();

            for(int j = 1 ; j <= n ; j++){

                if(visr[j])

                    continue;

                int ok = 1;

                int num = 0;

                int mark;

                int k;

                for(k = 1 ; k <= n ;k++)

                    if(a[j][k] != 0)

                        break;

//                printf("k = %d\n", k);

                if(k <= n)///这里没加=WA了无数

                    mark = a[j][k];

                else if(k > n){

                    visr[j] = 1;

                    continue;

                }

                for(; k <= n ; k++){

                    if(a[j][k] && a[j][k] != mark){

//                        printf("mark = %d, a[j][k] = %d, j = %d, k = %d\n", mark, a[j][k], j, k);

                        ok = 0; break;

                    }

                    if(a[j][k] != 0)

                        num++;

                }

                if(!ok)

                    continue;

//                output_a();

//                printf("x j = %d, mark = %d\n", j, mark);

                i++;

                if(num == 0){

                    visr[j] = 1;

                }

                else{

                    int lv_ok = 0;

                    int up = x[j].size();

                    for(k = 0 ; k < up ; k++)

                        if(v[x[j][k]] == mark && vis[x[j][k]] == 0){

//                            printf("j = %d, x[j][k] = %d, v[j][k] = %d\n", j, x[j][k], v[x[j][k]]);

                            ans[cnt++] = x[j][k];

                            vis[x[j][k]] = 1;

                            lv_ok = 1;

                        }

                    if(lv_ok)///这里没加WA了无数

                        for(k = 1 ; k <= n ; k++)

                            a[j][k] = 0;

                }

                visr[j] = 1;

            }

            for(int j = 1 ; j <= n ; j++){

                if(visc[j])

                    continue;

                int ok = 1;

                int num = 0;

                int mark;

                int k;

                for(k = 1 ; k <= n ; k++)

                    if(a[k][j])

                        break;

//                printf("j = %d, k = %d\n", j, k);

                if(k > n){

                    visc[j] = 1;

                    continue;

                }

                else if(k <= n)

                    mark = a[k][j];///这里写反WA了无数

                for(; k <= n ; k++){

                    if(a[k][j] && a[k][j] != mark){

//                        printf("j = %d, mark = %d, a[k][j] = %d\n", j, mark, a[k][j]);

                        ok = 0; break;

                    }

                    if(a[k][j] != 0)

                        num++;

                }

                if(!ok)

                    continue;

//                output_a();

//                printf("y j = %d, mark = %d\n", j, mark);

                if(num == 0){

                    visc[j] = 1;

                }

                else{

//                    totalok = 1;

                    int lv_ok = 0;

                    int up = y[j].size();

                    for(int k = 0 ; k < up ; k++)

                        if(v[y[j][k]] == mark && vis[y[j][k]] == 0){

//                            printf("j = %d, y[j][k] = %d, v[j][k] = %d\n", j, y[j][k], v[y[j][k]]);

                            ans[cnt++] = y[j][k];

                            vis[y[j][k]] = 1;

                            lv_ok = 1;

                        }

                    if(lv_ok)

                        for(int k = 1 ; k <= n ; k++)

                            a[k][j] = 0;

                }

                visc[j] = 1;

            }

        }

        for(int i = 1 ; i <= m ; i++)

            if(vis[i] == 0)

                ans[cnt++] = i;

        int f = 1;

        for(int i = m ; i >= 1 ; i--){

            if(f)   f = 0;

            else    printf(" ");

            printf("%d", ans[i]);

        }

        printf("\n");

    }

    return 0;

}

/*

1

3 5

0 0 0

0 0 0

0 0 0

3 3 3

3 3 3

3 3 3

L 1 3

L 2 2

L 2 3

L 3 3

L 1 3

*/

 

你可能感兴趣的:(HDU 5386 思维)