USACO-Party Lamps
题目来源:http://ace.delos.com/usacoprob2?a=eORCKYsuBVM&S=lamps
说真的,不怎么喜欢这题,主要是题意描述不好。
想了很久,终于明白,输入的亮着的灯,关着的灯,没有输入的就是未知的,状态可以随意。
这样,题目大意就是:
给出最后状态要满足的条件,然后求出从初始状态转换到最后状态过程中,所有满足要求的状态。
这么说来,就是一个简单的搜索题了。
分析:
考虑到,每种操作,如果操作两次,则什么都没干,由此,全部c>4的都可以归结到c<=4中。比如说,c=6,那它和c=4是完全一样的。这样,就可以大大地简化时间复杂度。这样,用DFS搜索每种操作的组合就是了。
NOCOW上有一个更深入的分析,但是我对此题没兴趣,主要是一开始时题意理解不好。程序写得挫了,但是这程序还是秒杀了此题。
/* ID:ay27272 PROG:lamps LANG:C++ */ #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> using namespace std; bool f[200]={0}; bool on[200]={0}; bool off[200]={0}; bool d[200]={0}; string s[10000]; int nn,n,sum,c; bool cmp(string a,string b) { return a<b; } bool check() { for (int i=1;i<=n;i++) { if (f[i]&&off[i]) return false; if (!f[i]&&on[i]) return false; } return true; } void work() { sum++; s[sum].clear(); for (int i=1;i<=n;i++) s[sum]=s[sum]+char(f[i]+'0'); } void dfs(int ss) { if (ss>c) { if (check()) work(); return; } dfs(ss+1); for (int i=1;i<=nn;i++) f[i]=!f[i]; dfs(ss+1); for (int i=1;i<=nn;i++) f[i]=!f[i]; for (int i=1;i<=nn;i+=2) f[i]=!f[i]; dfs(ss+1); for (int i=1;i<=nn;i+=2) f[i]=!f[i]; for (int i=2;i<=nn;i+=2) f[i]=!f[i]; dfs(ss+1); for (int i=2;i<=nn;i+=2) f[i]=!f[i]; for (int i=1;i<=nn;i+=3) f[i]=!f[i]; dfs(ss+1); for (int i=1;i<=nn;i+=3) f[i]=!f[i]; } int main() { freopen("lamps.in","r",stdin); freopen("lamps.out","w",stdout); scanf("%d%d",&n,&c); int tmp; scanf("%d",&tmp); while (tmp!=-1) { on[tmp]=1; scanf("%d",&tmp); } scanf("%d",&tmp); while (tmp!=-1) { off[tmp]=1; scanf("%d",&tmp); } while (c>4) c-=2; memset(f,true,sizeof(f)); nn=n; sum=0; dfs(1); if (!sum) cout<<"IMPOSSIBLE"<<endl; else { sort(s+1,s+sum+1,cmp); for (int i=1;i<=sum;i++) if (s[i]!=s[i-1]) cout<<s[i]<<endl; } return 0; }