USACO Party Lamps

参考:http://hi.baidu.com/enlighten09/blog/item/d9e9dac9147d260a01e9289d.html

是个可以很简单,仔细分析也可以很复杂的题目

首先,最后的灯亮的情况只有8种。每个操作只有做了和没做两种状态,所以4个操作就只有16种。把这16操作都实现一遍,就会发现只有8种最终状态了。分别是:

最终状态                                       按几次可以得到

0,0,0,0,0,0,                                  1,2,3

0,0,1,1,1,0,                                   2,3

 0,1,0,1,0,1,                                  1,2,3

0,1,1,0,1,1,                                   1,4

 1,0,0,1,0,0,                                  2,3

 1,0,1,0,1,0,                                  1,2

 1,1,0,0,0,1,                                   2,3

 1,1,1,1,1,1                                    0,2,3

而c>=5时,c是奇数等效于c=1或3,c是偶数等效于c=2或4,所以可以看出c>=5时,所有的状态都能被按出来

所以我把c分为0,<5,>=5三种情况讨论。

还有一点就是不管多少个灯,在一种状态中,都是以前六个灯得状态循环的,所以只用考虑6个灯。

我的代码——有一个大问题
当n > 4时,对表进行0-7行遍历即可

可是当n < 4时,0-7行是选择性的进行比较,我不知道应该怎么自动判断,所以自己写了n = 0, n = 1,n = 2的各种情况,太弱的写法了……
上面范例里的方法是用一个数组把n = 1, 2, 3, 4时对应的情况给列出,int first_four[4][8]={{0,2,3,4,-1},{0,1,2,4,5,6,7,-1},{0,1,2,4,6,7,-1},{3,-1}}; 本质上也一样……

/*
ID: wangxin12
PROG: lamps
LANG: C++
*/

#include <iostream>
#include <fstream>
#include <vector>
#include <string.h>
#include <stack>

using namespace std;

int N;
int count;
vector<int> ON;
vector<int> OFF;
vector<int> ans;
int lamp[8][6] = {
                {0,0,0,0,0,0},  
                {0,0,1,1,1,0},  
                {0,1,0,1,0,1},  
                {0,1,1,0,1,1},  
                {1,0,0,1,0,0},  
                {1,0,1,0,1,0},  
                {1,1,0,0,0,1},  
                {1,1,1,1,1,1},
};  //所有的8种final情况

bool check(int row);

int main() {	
	//input
	ifstream fin("lamps.in");
	ofstream fout("lamps.out");
	fin>>N;
	fin>>count;
	int temp = 0;
	while(true) {
		fin>>temp;
		if(temp != -1)
			ON.push_back(temp);
		else break;
	}
	while(true) {
		fin>>temp;
		if(temp != -1)
			OFF.push_back(temp);
		else break;
	}
	fin.close();
	

	//BODY
	int i, j;
	if(count > 2) {
		for(i = 0; i <= 7; i++) {
			if(check(i)) ans.push_back(i);
		}

		if(ans.empty()) fout<<"IMPOSSIBLE"<<endl;
		else {
			for(i = 0; i < ans.size(); i++) {
				for(j = 0; j < N; j++) {
					fout<<lamp[ans[i]][ (j % 6) ];
				}
				fout<<endl;
			}
		}
	}

	if(count == 0) {
		if(check(7)) ans.push_back(7);
		if(ans.empty()) fout<<"IMPOSSIBLE"<<endl;
		else {
			for(i = 0; i < ans.size(); i++) {
				for(j = 0; j < N; j++) {
					fout<<lamp[ans[i]][ (j % 6) ];
				}
				fout<<endl;
			}
		}
	}
	
	if(count == 1) {
		if(check(0)) ans.push_back(0);
		if(check(2)) ans.push_back(2);
		if(check(3)) ans.push_back(3);
		if(check(5)) ans.push_back(5);

		if(ans.empty()) fout<<"IMPOSSIBLE"<<endl;
		else {
			for(i = 0; i < ans.size(); i++) {
				for(j = 0; j < N; j++) {
					fout<<lamp[ans[i]][ (j % 6) ];
				}
				fout<<endl;
			}
		}
	}

	if(count == 2) {
		for(i = 0; i <= 7; i++) {
			if(i = 3) continue;
			if(check(i)) ans.push_back(i);
		}

		if(ans.empty()) fout<<"IMPOSSIBLE"<<endl;
		else {
			for(i = 0; i < ans.size(); i++) {
				for(j = 0; j < N; j++) {
					fout<<lamp[ans[i]][ (j % 6) ];
				}
				fout<<endl;
			}
		}
	}

	fout.close();

	return 0;
}

bool check(int row) {
	//check on
	for(int i = 0; i < ON.size(); i++) {
		if( !lamp[row][ (ON[i] % 6) - 1]) return false;
	}
	//check off
	for(int i = 0; i < OFF.size(); i++) {
		if( lamp[row][ (OFF[i] % 6) - 1]) return false;
	}

	return true;
}

另外几个可以有启发的范例:http://blog.csdn.net/liveas/article/details/5664822
牛逼的用位运算的:
http://www.byvoid.com/blog/usaco-224-party-lamps/zh-hans/
http://hi.baidu.com/leokan/blog/item/c12ddc432cf88e1772f05d0b.html


这个人的代码思路清晰 http://blog.csdn.net/sjtuyunlei/article/details/6648138




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值