您的位置:首页 > 其它

51NOD1337 翻转游戏 【贪心】

2017-09-06 21:41 323 查看
传送门

显然当没有'?'时,模拟一遍即可
当位置i是'?'时,如果后续的关卡中,位置i需要关灯,且当前关卡必须关掉一些灯,则顺手关掉
开灯也同理


#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))

using namespace std;

const int inf=1e9+7;
const int N = 50+5;

char str

;
int to

;//0:必须关,1必须开,2尽量关,3尽量开
int now
;

void initTo(int n,int m){
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
switch(str[i][j]){
case '-':
to[i][j]=0;
break;
case '+':
to[i][j]=1;
break;
case '?':
to[i][j]=2;
for(int k=i+1;k<n;++k){
if(str[k][j]!='?'){
to[i][j]=2+(str[k][j]=='+');
break;
}
}
break;
}
}
}
}

int slove(int n,int m){
initTo(n,m);
int ans=n;
MEM(now,0);
for(int i=0;i<n;++i){
bool mustOpen=0;
bool mustClose=0;
for(int j=0;j<m;++j){
if(to[i][j]==0&&now[j]==1){
mustClose=1;
}
if(to[i][j]==1&&now[j]==0){
mustOpen=1;
}
}
ans+=mustOpen+mustClose;
for(int j=0;j<m;++j){
if(to[i][j]<2){
now[j]=to[i][j];
}
if(mustClose&&to[i][j]==2){
now[j]=0;
}
if(mustOpen&&to[i][j]==3){
now[j]=1;
}
}
}
return ans;
}

int main(){
// freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i){
scanf("%s",str[i]);
}
printf("%d\n",slove(n,m));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  51NOD 贪心