列表

详情


NC202476. 交换游戏

描述

一列上有12个孔,这12个孔中有些孔被遮挡住了。
假定我们用 '-' 来表示没被遮挡住的孔,用 'o' 来表示被遮挡住的孔。
如果相邻的三个孔有两个孔被遮挡,并且被遮挡的两个孔相邻,就是 '-oo' 和 'oo-'。
对于这样的三个孔,我们可以将中间的孔的遮挡物移开,代价是将一端的遮挡物移到另一端没有被遮挡的孔上面。
对于一列给定的孔,你的任务是制定操作的顺序,使得最后剩余的被遮挡的孔的个数最少,并输出最后剩余的被遮挡的孔的个数。

输入描述

第一行输入一个
接下来n行,每行12个字符,代表孔的状态。

输出描述

对于每行输入在一行中输出一个数字代表答案。

示例1

输入:

5
---oo-------
-o--o-oo----
-o----ooo---
oooooooooooo
oooooooooo-o

输出:

1
2
3
12
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 7ms, 内存消耗: 720K, 提交时间: 2020-04-08 15:31:48

#include<cstdio>
#include<algorithm>
using namespace std;
int t,f[1<<13];
char s[20];
int dfs(int x){
	if(f[x]||!x){
		return f[x];
	}
	int cnt=__builtin_popcount(x);
	for(int i=1;i<=10;i++){
		if((x&(1<<i))&&(((x>>(i-1))&1)^(x>>(i+1))&1)){
			cnt=min(cnt,dfs(x^(7<<(i-1))));
		}
	} 
	return f[x]=cnt;
}
int main(){
	scanf("%d",&t);
	while(t--){
		int x=0;
		scanf("%s",s+1);
		for(int i=1;i<=12;i++){
			x=(x<<1)+(s[i]=='o'?1:0);
		}
		printf("%d\n",dfs(x));
	}
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 10ms, 内存消耗: 552K, 提交时间: 2020-03-15 13:56:40

#include<bits/stdc++.h>
using namespace std;
int f[1<<12];
int n;
char s[20];
int dfs(int x)
{
	if(f[x]||x==0) return f[x];
	int ans=0;
	for(int i=0;i<12;i++)
	{
		if(x>>i&1) ans++;
	}
	for(int i=0;i<10;i++)
	{
		if( x>>i+1&1 && x>>i&1 ^ x>>i+2&1) ans=min(ans,dfs(x^(7<<i)));
	}
	f[x]=ans;
	return ans;
}	
int main()
{
	scanf("%d",&n);
	while(n--)
	{
		scanf("%s",s);
		int x=0;
		for(int i=0;i<12;i++)
		{
			x=(x<<1)+(s[i]=='o'? 1:0);
		}
		printf("%d\n",dfs(x));
	}
}

上一题