1902 翻硬币
有N枚硬币,编号1到N。现在有如下4种操作:
1、翻转所有硬币,即正的变成反的,反的变成正的。
2、翻转所有奇数号的硬币。
3、翻转所有偶数号的硬币。
4、翻转所有编号形式为 3M+1(M>=0)3M+1(M>=0) 的硬币。
刚开始的时候所有硬币都是正面朝上,现在给出经过P次操作之后某些硬币的正反状态,请计算一下P次操作之后,有哪些状态符合这些条件。
输入单组测试数据。
第一行有两个整数N(10 <= N <= 100)和P(1 <= P <= 10000 )。
第二行给出若干个整数(不超过N个),表示最后正面朝上的硬币编号,输入-1结束。
第三行给出若干个整数(不超过N个),表示最后反面朝上的硬币编号,输入-1结束。
输出所有符合条件的最终状态。每行一个,输出N个字符,第i个字符表示第i个硬币的状态,1表示正面朝上,0代表反面朝上。按照字典序从小到大输出,如果没有符合要求的最终状态,输出IMPOSSIBLE。
样例输入1
10 2
-1
7 -1
样例输出1
0000000000
0011100011
0101010101
第一眼看到可能是深搜问题,递归改变状态,可以实现,但针对比较大的数据就会超时,后来仔细研究了一下题得出
每种操作同时操作两次会变回原状态,也就是说每种只有操作了一次和没有操作,通过对四种方法做和不做的组合,一共有2的4次方16种状态,只要根据p的数据对于2取余判断奇偶性,再和16种状态中的奇偶性对比就行了
java代码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class jjj {
static ArrayList<Integer> z = new ArrayList<Integer>();//存储最后正面的状态
static ArrayList<Integer> f = new ArrayList<Integer>();//存储最后反面的状态
static ArrayList<String> max = new ArrayList<String>();//存储最后的情况
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] l = new int[n];//表示当前的状态
for (int i = 0; i < l.length; i++) {
l[i]=1;//初识状态为一
}
int p = sc.nextInt();
int zz = sc.nextInt()-1;//正面的状态
while (zz>=0) {
z.add(zz);
zz=sc.nextInt()-1;
}
int ff = sc.nextInt()-1;//反面的状态
while (ff>=0) {
f.add(ff);
ff=sc.nextInt()-1;
}
String s = "";
if (p%2==0) {//偶数情况
if (p(l)) {//不操作
for (int i : l) {
s+=i;
}
if (!max.contains(s)) {
max.add(s);
}
s="";
}
if (p>=2) {//操作两次
for (int i = 1; i <= 4; i++) {
for (int j = i+1; j <= 4; j++) {
fz(l,i);
fz(l,j);
if (p(l)) {
for (int in : l) {
s+=in;
}
if (!max.contains(s)) {
max.add(s);
}
s="";
}
fz(l,j);
fz(l,i);
}
}
}
if (p%4==0&&p>=4) {//操作四次
fz(l,4);
if (p(l)) {
for (int in : l) {
s+=in;
}
if (!max.contains(s)) {
max.add(s);
}
s="";
}
fz(l,4);
}
}
if (p%2==1) {//奇数情况
for (int i = 1; i <= 4; i++) {//一次情况
fz(l,i);
if (p(l)) {
for (int in : l) {
s+=in;
}
if (!max.contains(s)) {
max.add(s);
}
s="";
}
fz(l,i);
}
if (p>=3) {
for (int i = 1; i <= 4; i++) {//三次情况
for (int j = i+1; j <= 4; j++) {
for (int k = j+1; k <= 4; k++) {
fz(l,i);
fz(l,j);
fz(l,k);
if (p(l)) {
for (int in : l) {
s+=in;
}
if (!max.contains(s)) {
max.add(s);
}
s="";
}
fz(l,k);
fz(l,j);
fz(l,i);
}
}
}
}
}
if (max.size()==0) {//无满足状态
System.out.println("IMPOSSIBLE");
return;
}
Collections.sort(max);//排序字典序输出
for (int i = 0; i < max.size(); i++) {
System.out.println(max.get(i));
}
}
private static void fz(int[] l, int i) {//1234种操作
if (i==1) {
for (int j = 0; j < l.length; j++) {
l[j]=1-l[j];
}
}else if(i==2){
for (int j = 0; j < l.length; j+=2) {
l[j]=1-l[j];
}
}else if (i==3) {
for (int j = 1; j < l.length; j+=2) {
l[j]=1-l[j];
}
}else if (i==4) {
for (int j = 0; j < l.length; j+=3) {
l[j]=1-l[j];
}
}
}
private static boolean p(int[] l) {//判断是否满足条件
if (z.size()!=0) {
for (int i = 0; i < z.size(); i++) {
if (l[z.get(i)]!=1) {
return false;
}
}
}
if (f.size()!=0) {
for (int i = 0; i < f.size(); i++) {
if (l[f.get(i)]!=0) {
return false;
}
}
}
return true;
}
}
代码量较多,希望有大佬可以给指点指点