您的位置:首页 > 其它

POJ 3279 + UVA 11464 (二维翻转水题)

2015-12-04 21:49 399 查看
http://poj.org/problem?id=3279

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2459

两题都是翻转一个数,然后它的上下左右都跟着变化。

这种题目的做法是用DFS枚举出第一行的所有状态,当第一行的状态确定之后,那么下面的状态也唯一了。因为下一行总是依赖上一行。然后对于每种状态check后求值就可了。

POJ代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 20;
const int INF = 0x3f3f3f3f;
int ismap

;
int ans

,n,m,now,res=INF;
int cnt

;
int pre

;
int change
;

bool check(int k)
{
if(k==n+1)
{
for(int i=1;i<=m;i++)
{
if(pre[k-1][i]) return false;
}
return true;
}

for(int i=1;i<=m;i++)
{
if(pre[k-1][i])
{
cnt[k][i]++;
now++;
pre[k-1][i] = 0;
pre[k][i] = pre[k][i] ? 0 : 1 ;
if(i>1) pre[k][i-1] = pre[k][i-1] ? 0: 1;
if(i<m) pre[k][i+1] = pre[k][i+1] ? 0 : 1;
if(k+1<=n) pre[k+1][i] = pre[k+1][i] ? 0 : 1;
}
}
check(k+1);
}

void dfs(int num)
{
if(num==m+1)
{
for(int i=1;i<=m;i++)
{
if(!change[i]) continue;

now ++;
cnt[1][i] ++;
pre[1][i] = pre[1][i] ? 0 : 1;
if(n>=2) pre[2][i] = pre[2][i] ? 0: 1;
if(i>1) pre[1][i-1] = pre[1][i-1] ? 0 : 1;
if(i<m) pre[1][i+1] =  pre[1][i+1] ? 0: 1;
}

if(check(2) && now < res)
{
memcpy(ans,cnt,sizeof(ans));
res = now;
}

now = 0;
memset(cnt,0,sizeof(cnt));
memcpy(pre,ismap,sizeof(pre));
return;
}

for(int ch = 0; ch<2 ; ch++)
{
if(!ch) dfs(num+1);
else
{
change[num] = 1;
dfs(num+1);
change[num] = 0;
}
}
return;
}

int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&ismap[i][j]),pre[i][j] = ismap[i][j];

now = 0;
res = INF;
memset(cnt,0,sizeof(cnt));
memset(change,false,sizeof(change));
dfs(1);

if(res==INF) printf("IMPOSSIBLE\n");
else
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) printf("%d%c",ans[i][j],j==m?'\n':' ');
}
return 0;
}


UVA代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 20;
const int INF = 0x3f3f3f3f;
int party

;
int num

,n;
int tmp

,now,ans;
bool change
;

int sum(int i,int j)
{
int sum = 0;
if(i-1>=1) sum+=num[i-1][j];
if(i+1<=n) sum+=num[i+1][j];
if(j-1>=1) sum+=num[i][j-1];
if(j+1<=n) sum+=num[i][j+1];

return sum;
}

void update(int i,int j)
{
if(i-1>=1)  tmp[i-1][j]++;
if(i+1<=n)  tmp[i+1][j]++;
if(j-1>=1)  tmp[i][j-1]++;
if(j+1<=n)  tmp[i][j+1]++;
return;
}

bool check(int k)
{
if(k==n+1)
{
for(int i=1;i<=n;i++)
if(tmp
[i]%2) return false;
return true;
}

for(int i=1;i<=n;i++)
{
if(tmp[k-1][i]%2)
{
if(num[k][i]) return false;
now ++;
update(k,i);
}
}
check(k+1);
}

void dfs(int x)
{
if(x==n+1)
{
for(int i=1;i<=n;i++)
{
if(!change[i]) continue;

now++;
update(1,i);
}

if(check(2)) ans = min(ans,now);

memcpy(tmp,party,sizeof(tmp));
now = 0;
return;
}

if(num[1][x]) dfs(x+1);
else
{
for(int ch = 0; ch<2; ch++)
{
if(!ch) dfs(x+1);
else{
change[x] = true;
dfs(x+1);
change[x] = false;
}
}
}
return;
}

int main()
{
int T;
scanf("%d",&T);
for(int cas = 1;cas<=T;cas++)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)  scanf("%d",&num[i][j]);

for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)  party[i][j] = sum(i,j);

memset(change,false,sizeof(change));
memcpy(tmp,party,sizeof(tmp));
now = 0;
ans = INF;
dfs(1);

if(ans ==INF) ans = -1;
printf("Case %d: %d\n",cas,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: