HDU 5386
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5386
题意:
给两个矩阵S和T,给一些操作,操作可以把一行或一列全变成一个数字。问操作顺序。SPJ
思路:
思维题,因为一定有解,所以反着来只看目标矩阵,每次找满足条件的行或列,满足的条件是除了被访问过的点,其余点都相同,然后存不存在这样的操作,(注意,这里WA了无数)如果存在,则把该行或该列设置为访问过。
题解或者标程有错,如果出现极限数据如
2 |
3 |
1 |
3 |
4 |
4 |
1 |
3 |
2 |
2 |
2 |
3 |
4 |
4 |
4 |
4 |
复杂度会变成o(m!)
只有每次都只遍历图然后查询是否有类似操作的O(n^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
*/