poj 3185

这个题可以用高斯消元来解,那就是水题

不过有很多有意思的解法,例举一二



1贪心:


从左到右枚举一边(每个硬币翻还是不翻仅由其前面的硬币的状态决定)

但是有这种情况:


110000000...(省略n多个0)


可证,反而是从第一个开始翻就比较好


这样就从右再向左枚举一边

两次枚举,得结果


也可这样看,枚举第一个硬币翻还是不翻


代码一:

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
int num[40]={0},nc[40]={0};
int deal(int a){
    if(a==0)return 1;
    if(a==1)return 0;
}
int Min(int a,int b){
    if(a<b)return a;
    return b;
}
int main(){
    int tmp1,tmp2;
    int cnt=200;
    for(int i=1;i<=20;i++){
        scanf("%d",&num[i]);
        nc[i]=num[i];
    }
    tmp1=0;// 1fanzhuan
    //num[1]=!num[1];
    for(int i=1;i<=20;i++){
        if(num[i-1]){
            num[i-1]=0;
            num[i]=deal(num[i]);
            num[i+1]=deal(num[i+1]);
            tmp1++;
        }
    }
    tmp2=0;//1bufanzhuan
    //nc[1]=nc[1];
    for(int i=19;i>=0;i--){
        if(nc[i+1]){
            nc[i+1]=0;
            nc[i]=deal(nc[i]);
            nc[i-1]=deal(nc[i-1]);
            tmp2++;
        }
    }
    cnt=Min(tmp1,tmp2);
    printf("%d\n",cnt);

}

代码二:

#include <iostream>
using namespace std;
int bowl[25]={0},flip[25]={0};
int main()
{
	int i,cnt=100,tmp;
	for (i=1;i<21;i++)		cin >> bowl[i];

	flip[1] = tmp = 1;		//翻第一个
	for (i=2;i<21;i++)
		if ( flip[i] = (flip[i-2]^flip[i-1]^bowl[i-1]) )		tmp++;
	if ( tmp<cnt && (flip[19]^flip[20]^bowl[20])==0 )			cnt = tmp;


	flip[1] = tmp = 0;		//不翻第一个
	for (i=2;i<21;i++)
		if ( flip[i] = (flip[i-2]^flip[i-1]^bowl[i-1]) )		tmp++;
	if ( tmp<cnt  && (flip[19]^flip[20]^bowl[20])==0 )		cnt = tmp;
	cout << cnt << endl;

	return 0;
}


2暴搜:

详见代码


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

int num[27],step,flag;
int range()
{
    int i;
    for(i=0;i<20;i++)
        if(num[i]==1)
            return 0;
    return 1;
}
void turn(int i)
{
    num[i]=!num[i];
    if(i>0)
        num[i-1]=!num[i-1];
    if(i<19)num[i+1]=!num[i+1];
}
void DFS(int i,int dp)
{
    if(step==dp){
        flag=range();//flag=1 fail
        return;
    }
    if(i>=20||flag)return;
    turn(i);
    DFS(i+1,dp+1);//i zhuan
    turn(i);
    DFS(i+1,dp);//i buzhuan
}
int main()
{
    int i;
    for(i=0;i<20;i++)
        scanf("%d",&num[i]);
    for(step=0;step<20;step++)
    {
        flag=0;
        DFS(0,0);
        if(flag)break;
    }
    printf("%d\n",step);
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值