USACO 4.4 shuttle puzzle
起初用搜索,写了好多,bfs+位运算。。。然后STL的队列给MLE了。。。但是算出的结果是正确的,然后接着是TLE。。。
虽然用搜索没有挂,但是不得不说又练了一下代码能力,还是有不少收获的,呵呵。。
正确的算法是找规律,详细的做法看nocow吧,这里贴个代码:
搜索:
View Code
/*
ID: zlqest11
LANG: C++
TASK: shuttle
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <utility>
using namespace std;
//file stream declare
FILE fin, fout;
//data structure
const int N = 1000000;
set < pair<short, int> > hash;
queue < pair<short, int> > q;
int n, start, target;
int head, tail, step[N], pre[N], mid[N];
vector < pair <short, int> > ans;
void mkbit(int &x, int pos, int flag){
int tmp;
if(flag == 0){
tmp = 1<<pos;
tmp = ~tmp;
x &= tmp;
}
else{
tmp = 1<<pos;
x |= tmp;
}
}
void b_bfs(){
//init
memset(step, -1, sizeof(step));
memset(pre, -1, sizeof(pre));
//search process
pair <short, int> u, tmp;
short pos;
int key, xx;
head = tail = 0;
while(!q.empty()){
u = q.front();
q.pop();
pos = u.first;
key = u.second;
if(pos < n*2){
tmp.first = pos+1;
tmp.second = key;
if(hash.find(tmp) == hash.end()){
hash.insert(tmp);
q.push(tmp);
step[++tail] = pos;
pre[tail] = head;
mid[tail] = pos;
if(tmp.second==target && tmp.first==n) return;
}
}
if(pos >= 1){
tmp.first = pos-1;
tmp.second = key;
if(hash.find(tmp) == hash.end()){
hash.insert(tmp);
q.push(tmp);
step[++tail] = pos-1;
pre[tail] = head;
mid[tail] = pos;
if(tmp.second==target && tmp.first==n) return;
}
}
if(n*2-pos >= 2){
tmp.second = key;
if(key&(1<<pos+1)) mkbit(tmp.second, pos, 1);
else mkbit(tmp.second, pos, 0);
if(key&(1<<pos)) mkbit(tmp.second, pos+1, 1);
else mkbit(tmp.second, pos+1, 0);
tmp.first = pos+2;
if(hash.find(tmp) == hash.end()){
hash.insert(tmp);
q.push(tmp);
step[++tail] = pos+1;
pre[tail] = head;
mid[tail] = pos;
if(tmp.second==target && tmp.first==n) return;
}
}
if(pos >= 2){
tmp.second = key;
if(key&(1<<pos-1)) mkbit(tmp.second, pos-2, 1);
else mkbit(tmp.second, pos-2, 0);
if(key&(1<<pos-2)) mkbit(tmp.second, pos-1, 1);
else mkbit(tmp.second, pos-1, 0);
tmp.first = pos-2;
if(hash.find(tmp) == hash.end()){
hash.insert(tmp);
q.push(tmp);
step[++tail] = pos-2;
pre[tail] = head;
mid[tail] = pos;
if(tmp.second==target && tmp.first==n) return;
}
}
head++;
}
}
void Print(int tail){
if(tail == 0) return;
else{
Print(pre[tail]);
ans.push_back(make_pair(mid[tail], step[tail]));
}
}
int main()
{
freopen("shuttle.in", "r", stdin);
//freopen("shuttle.out", "w", stdout);
scanf("%d", &n);
//pre init
start = target = 0;
for(int i = 1; i <= n; i++) start = (start<<1) + 1;
target = (start<<n);
q.push(make_pair(n, start));
hash.insert(make_pair(n, start));
b_bfs();
Print(tail);
pair <short, int> tmp;
for(int i = 0; i < ans.size(); i++){
tmp = ans[i];
if(i && i%20==0) printf("\n");
if(i%20) putchar(' ');
printf("%d", 2*n-tmp.second+(tmp.first>tmp.second ? 1:0));
}
printf("\n");
return 0;
}
找规律的AC代码:
View Code
/*
ID: zlqest11
LANG: C++
TASK: shuttle
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, ct, table[500], ans[500];
int main()
{
freopen("shuttle.in", "r", stdin);
freopen("shuttle.out", "w", stdout);
scanf("%d", &n);
if(n == 1) printf("1 3 2\n");
else{
ct = 0;
if(n & 1){
for(int i = 3; i <= n; i += 2){
table[++ct] = 1;
for(int j = 1; j < i; j++) table[++ct] = -2;
table[++ct] = -1;
for(int j = 1; j <= i; j++) table[++ct] = 2;
}
for(int i = ct-n; i > 0; i--)
table[++ct] = table[i];
}
else{
for(int i = 2; i <= n; i += 2){
table[++ct] = 1;
for(int j = 1; j <= i; j++) table[++ct] = -2;
if(i == n) break;
table[++ct] = -1;
for(int j = 1; j <= i+1; j++) table[++ct] = 2;
}
for(int i = ct-n; i > 0; i--) table[++ct] = table[i];
}
//for(int i = 1; i <= ct; i++) printf("%d ", table[i]);
//printf("\n");
int tail = 0;
ans[++tail] = n;
ans[++tail] = ans[tail-1]+2;
for(int i = 1; i <= ct; i++)
ans[++tail] = ans[tail-1] + table[i];
ans[++tail] = ans[tail-1] + 2;
ans[++tail] = ans[tail-1] - 1;
for(int i = 1; i <= tail; i++){
if(i%20 != 1) putchar(' ');
printf("%d", ans[i]);
if(i%20 == 0) printf("\n");
}
if(tail%20 != 0) printf("\n");
}
return 0;
}