您的位置:首页 > 其它

hdu5755Gambler Bo

2016-07-27 10:11 288 查看

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5755

题意:给定一个只含{0,1,2}的n*m的矩阵。有一种操作:将(x,y)位置+2同时(x-1,y),(x+1,y),(x,y-1),(x,y+1)都会+1。要求进行<=2*n*m次操作将矩阵变为全0,数据保证至少有一组解。

分析:前段时间刚做完一道这样的题,比赛的时候因为卡其他题了这道题却没看到。想多练一下的转E.Harmonious Matrices。。再说下这种题的思路吧,我们可以设第一行每个位置的操作次数为xi,0<=xi<3,然后显然知道了第一行我们就能将整个矩阵都推导出来。如果直接暴力枚举显然是不行的,我们观察发现每填完一行只能确定上一行的元素,那么想要确定n行显然是要推到第n+1行,但是实际情况第n+1行全为0。所以对于第n+1行的m个位置我们能得到m个含m个未知数xi等于0的方程,那么只要解这个方程组就能得到答案x啦。PS:出题人的做法类似但是复杂度上差很多,出题人说的做法是设n*m个变量,然后根据题目的要求建n*m个方程,这样是O(n^3*m^3)的。我的做法是设m个变量,这样就能O(m^3)啦。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=35;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const int MAX=2000000010;
const ll INF=1ll<<55;
const double pi=acos(-1.0);
typedef double db;
typedef unsigned long long ull;
int a

,p

,f

;
int get(int i,int j,int k) {
int sum=(f[i][j-1][k]+2*f[i][j][k]+f[i][j+1][k]+f[i-1][j][k])%3;
return ((3-sum)%3+3)%3;
}
int getans(int i,int j) {
int sum=(p[i][j-1]+2*p[i][j]+p[i][j+1]+p[i-1][j]+a[i][j])%3;
return ((3-sum)%3+3)%3;
}
void gauss(int n,int m) {
int d,i,j,k,h,w=0;
for (i=1,j=1;j<m;j++,w=0) {
for (k=i;k<=n;k++)
if (p[k][j]) w=k;
if (w) {
for (k=j;k<=m;k++) swap(p[i][k],p[w][k]);
for (k=i+1;k<=n;k++)
if (p[k][j]) {
d=(p[k][j]*p[i][j]%3+3)%3;
for (h=j;h<=m;h++) p[k][h]=((p[k][h]-d*p[i][h])%3+3)%3;
}
i++;
}
if (i>n) break ;
}
for (j=1;j<=m;j++) f[1][j][j]=0;
for (j=i-1;j;j--) {
for (k=1;k<m;k++)
if (p[j][k]) break ;
for (d=0,h=k+1;h<m;h++)
if (f[1][h][h]&&p[j][h]) d=(d+f[1][h][h]*p[j][h])%3;
f[1][k][k]=p[j][k]*(3-d+p[j][m])%3;
}
memset(p,0,sizeof(p));
for (j=1;j<=m;j++) p[1][j]=(f[1][j][j]+3)%3;
}
int main()
{
int i,j,k,n,m,t,ans;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
memset(a,0,sizeof(a));
for (i=1;i<=n;i++)
for (j=1;j<=m;j++) scanf("%d", &a[i][j]);
memset(f,0,sizeof(f));
for (i=1;i<=m;i++) f[1][i][i]=1;
for (i=2;i<=n+1;i++)
for (j=1;j<=m;j++) {
f[i][j][m+1]=(3-a[i-1][j]+get(i-1,j,m+1))%3;
for (k=1;k<=m;k++) f[i][j][k]=get(i-1,j,k);
}
memset(p,0,sizeof(p));
for (i=1;i<=m;i++) {
p[i][m+1]=((3-f[n+1][i][m+1])%3+3)%3;
for (j=1;j<=m;j++) p[i][j]=f[n+1][i][j];
}
gauss(m,m+1);ans=0;
for (i=1;i<=m;i++) ans+=p[1][i];
for (i=2;i<=n;i++)
for (j=1;j<=m;j++) p[i][j]=getans(i-1,j),ans+=p[i][j];
printf("%d\n", ans);
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
for (k=1;k<=p[i][j];k++) printf("%d %d\n", i, j);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: