首页 > 代码库 > uva 279 - Spin(递推)
uva 279 - Spin(递推)
题目链接:uva 279 - Spin
题目大意:进行一个游戏,给出初始状态,要求问说最少多少步可以让所有的环移动出来。移动规则如图所示。
解题思路:一开始以为是隐式图搜索,写完TLE了。后来发现这道题和汉诺塔是一个思路,都是采取最优策略,并且说左边环的状态不会影响右边环。所以dp[i]表示从右边数,第i个为v,其他均为h的步数(由全h变换至)。
模拟最优过程有dp[i]=dp[i?1]?2+i?2?1
对已给定状态,可看做由全h变换到该状态的步数。根据容斥原理,第奇数个v为加,偶数个v为减。最后还要考虑到pos。
C++ TLE#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 50;
const ll mod = 30;
struct state {
ll s, c;
state (ll s, ll c) {
this->s = s;
this->c = c;
}
};
int n, k;
inline bool ispos (ll pos, ll s) {
if (pos >= n)
return true;
return !(s & (1<<pos));
}
inline ll cal (char* str, ll pos) {
ll ans = 0;
for (int i = 0; i < n; i++) {
if (str[i] == ‘v‘)
ans |= (1<<i);
}
return ans * mod + pos;
}
ll bfs (ll S) {
queue<state> que;
que.push(state(S, 0));
map<ll, int> g;
g[S] = 1;
while (!que.empty()) {
state u = que.front();
que.pop();
//printf("%lld %lld\n", u.s, u.c);
if (u.s == 0)
return u.c + 2;
ll pos = u.s % mod, s = u.s / mod;
// left;
if (pos > 0 && ispos(pos + 1, s) ) {
ll v = s * mod + pos - 1;
if (!g.count(v)) {
// printf("left!\n");
g[v] = 1;
que.push(state(v, u.c+1));
}
}
// right;
if (pos < n-1 && (pos >= n - 2 || (ispos(pos + 2, s) && ispos(pos + 3, s))) ) {
ll v = s * mod + pos + 1;
if (!g.count(v)) {
// printf("rignt!\n");
g[v] = 1;
que.push(state(v, u.c+1));
}
}
if ( pos == n-1 || !ispos(pos+1, s)) {
ll v = (s^(1<<pos)) * mod + pos;
if (!g.count(v)) {
// printf("change!\n");
g[v] = 1;
que.push(state(v, u.c+1));
}
}
}
return -1;
}
int main () {
int pos, cas;
char str[maxn];
scanf("%d", &cas);
while (cas--) {
scanf("%d%s%d", &n, str, &pos);
printf("%lld\n", bfs(cal(str, pos-1)));
}
return 0;
}
C++ AC#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 30;
int main () {
int cas, n;
ll pos, dp[maxn+5];
char str[maxn+5];
dp[0] = 0;
for (int i = 1; i <= maxn; i++)
dp[i] = (dp[i-1] + i) * 2 - 1;
scanf("%d", &cas);
while (cas--) {
scanf("%d%s%lld", &n, str, &pos);
ll ans = 0, sign = 1;
for (int i = 0; i < n; i++) {
if (str[i] == ‘v‘) {
ans += (sign * dp[n-i]);
sign *= -1;
}
}
printf("%lld\n", ans + pos + 1);
}
return 0;
}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。