hdu 4949 Light 插头dp

Light

Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 105    Accepted Submission(s): 42


Problem Description
Teacher Mai has a board of n rows and m columns. There is a light in each cell.

He can flip some lights: if this light is on, turn it off, else turn it on.

He can choose a cell(i,j), and he has following two operations:

1. Flip the light on the cells which share a common edge with cell(i,j).
2. Flip the light on the cells which share a common edge with cell(i,j) and cell(i,j).
  
You are given the initial state of board. Output the minimum operations to turn off the all the lights.
 

Input
There are multiple test cases, terminated by a line "0 0".

For each test case, the first line contains two integers n,m(1<=n,m<=10).

In following n lines, each line contains a string consisting of m characters, representing the initial state(0 means off, 1 means on).
 

Output
For each case, output "Case #k: ans" first, where k is the case number counting from 1, ans is the minimum operations.
 

Sample Input
  
  
3 3 111 111 111 3 3 000 010 000 0 0
 


Sample Output
   
   
Case #1: 3 Case #2: 2 

题意:一个地图有1,0符号,两种操作1.把一个点周围四个点取反,2,把一个点周围和自己取反,
问全部都是0至少几步操作

状态:0表示这个位置为0,没有操作过,1表示这个位置为0操作过1次,2表示这个位置为1没有操作过
因为操作偶数次周围四个点不变,奇数次周围四个点会改变
对于一个点,上方和左方操作次数确定后,可以确定这个点状态,这个点可以操作0,1,2次,
注意:确保每次上方的点都会变成0或1状态,如果i=0,这个点操作1次要忽略上方的状态,一个点操作两次,可以变成0或2的状态


#include<cstdio>

inline void min(int &x,int y){
    x>y?x=y:0;
}
int len[15];
int dp[2][60000];
char word[11][11];
void init(){
    len[0]=1;
    for(int i = 1;i <= 14;i++)
        len[i] = len[i-1]*3;
}
int nextstate(int v,int n,int i,int s){
    if(i == 0)  return s+n;
    if(n==1) {
        if(v == 0) v = 2;
        else if(v == 2) v = 0;
    }
    return v*len[i-1]+n*len[i]+s;
}
int main(){
    freopen("1005.in","r",stdin);
    freopen("10051.out","w",stdout);
    init();
    int n,m,tt=1;
    int i,j,k,u,v,no,s,s1,s2;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0)return 0;
        for( i = 0;i < n; i++){
            getchar();
            for(j=0;j<m;j++)
                word[i][j]=getchar();

            //scanf("%s",word[i]);
        }
        int p=0,q=1;
        for( i=0;i<len[m];i++)dp[0][i]=1000000;
        dp[0][0] = 0;
        for( i = 0;i < n;i++){
            for( j = 0;j < m;j++){
                for(k=0;k<len[m];k++)dp[q][k]=1000000;
                for(k=0;k<len[m];k++){
                    u = k/len[j]%3;
                    v = j==0?0:k/len[j-1]%3;
                    s2 = j==0?k-u*len[j]:k-u*len[j]-v*len[j-1];
                    no=word[i][j]-'0';
                    if((u+v)&1)no^=1;
                    if(u == 2){
                        s = nextstate(v,1,j,s2);
                        min(dp[q][s],dp[p][k]+1);
                    }
                    else if(u == 1){
                        if(no == 0){
                            s = nextstate(v,0,j,s2);
                            min(dp[q][s],dp[p][k]);
                            s = nextstate(v,1,j,s2);
                            min(dp[q][s],dp[p][k]+1);
                        }
                        else if(no == 1){
                            s = nextstate(v,2,j,s2);
                            min(dp[q][s],dp[p][k]);
                            s = s-2*len[j];
                            min(dp[q][s],dp[p][k]+2);
                            s = nextstate(v,1,j,s2);
                            min(dp[q][s],dp[p][k]+1);

                        }
                    }
                    else if(u == 0){
                        s = nextstate(v,0,j,s2);
                        if(no==0)min(dp[q][s],dp[p][k]);
                        min(dp[q][s],dp[p][k]+2);
                        s=s+2*len[j];
                        if(no==1)min(dp[q][s],dp[p][k]);
                        min(dp[q][s],dp[p][k]+2);
                    }
                    if(i==0) {
                        s1 = nextstate(v,1,j,s2);
                        min(dp[q][s1],dp[p][k]+1);
                    }
                }
               k=p,p=q,q=k;
            }
        }
        int ans = 100000,flag;
        for(i = 0;i < len[m];i++){
            flag = 1;
            for( j=0;j<m;j++)
                if((i/len[j])%3==2)flag=0;
            if(flag==1)min(ans,dp[p][i]);
        }
        printf("Case #%d: %d\n",tt++,ans);
    }
    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值