[usaco]1.5 Checker Challenge

拿到題目我的第一反應是八皇后問題,順利的寫出了遞歸解法,弄完這個,感覺自己寫遞歸和回溯有了一定的進步了,至此第一章做完了,再接再厲。

但是提交後,在13 這個測試樣例超時,然後就在想怎麼剪枝

  • 之前在判斷放棋子是否衝突的時候,是在放的位置往四個方向拓展,如果沒有衝突就放 。現在改進爲直接判斷 和之前放置的棋子是否衝突。
  • 對稱剪枝,這個在百度之後才知道的 ,這個是關鍵,直接砍掉一般的時間
還有說是用位運算,這個不熟,下次去學一下。
Executing...
Test 1: TEST OK [0.000 secs, 3340 KB]
Test 2: TEST OK [0.000 secs, 3340 KB]
Test 3: TEST OK [0.000 secs, 3340 KB]
Test 4: TEST OK [0.011 secs, 3340 KB]
Test 5: TEST OK [0.011 secs, 3340 KB]
Test 6: TEST OK [0.043 secs, 3340 KB]
Test 7: TEST OK [0.162 secs, 3340 KB]
Test 8: TEST OK [0.670 secs, 3340 KB]
/*
ID:fuxiang2
PROG: checker
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <stack>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <list>
#include <algorithm>
#include <set>
#include <cmath>
#include <cstring>
#include <cstdlib>
 
#define REP(i, n) for (int i=0;i<int(n);++i)
#define FOR(i, a, b) for (int i=int(a);i<int(b);++i)
#define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)
#define REP_1(i, n) for (int i=1;i<=int(n);++i)
#define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)
#define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)
#define EACH(it, A) for (typeof(A.begin()) it=A.begin(); it != A.end(); ++it)
 
using namespace std;
ofstream fout ("checker.out");
ifstream fin ("checker.in");
 
const int N = 14;
int graph[N][N];
int n;
int ans ;
int result ;
// 類似八皇后問題
int used[N];
//list <int >path;
int path[N];
 
bool isok(int x,int y)
{
    if(x >=1 && x<= n && y >= 1 && y <= n)
        return true;
    return false;
}
int dir[4][2] = { {-1,-1} ,{-1,1},{1,1},{1,-1} };
bool check(int x,int y )
{
    int nx = x;
    int ny = y;
    int n = x -1;
    if(n == 0)
        return true;
 
    FOR_1(i,1,n){
        nx = i;
        ny = path[i];
        if( abs(x-nx) == abs(y-ny))
            return false;
    }
    return true;
 
    //FOR_1(i,0,3){
    //    nx = x +  dir[i][0];
    //    ny = y +  dir[i][1];
    //    while(isok(nx,ny) ){
    //        if(graph[nx][ny] == 1)
    //            return false;
    //        nx += dir[i][0];
    //        ny += dir[i][1];
    //    }
    //}
    //return true;
 
}
 
void place(int col,int row)
{
    graph[row][col] = 1;
    if(row== n){
        ans ++;
        if(result + ans <= 3){
            //list<int >::iterator iter = path.begin();
            //fout<< *iter;
            fout<<path[1];
            //for(iter ++ ; iter != path.end() ; iter ++)
            for(int i = 2 ; i <= n ; i ++)
                fout <<" "<< path[i];
            fout<<endl;
        }
        graph[row][col] = 0;
        return ;
    }
    FOR_1(i,1,n){
        if(used[i] == 0 && check(row+1,i ) == true )
        {
            path[row+1] = i;//path.push_back(i);
            used[i] = 1;
            place(i,row+1);
            //path.pop_back();
            used[i] = 0;
        }
    }
    graph[row][col] = 0;
 
}
void work(int n)
{
    result = 0;
 
    FOR_1(j,1,n/2) {// 列
        path[1] = j;//path.push_back(j);
        used[j]  = 1;
        place(j,1);
        //path.pop_back();
        used[j] = 0;
    }
    int re =  ans;
    result = ans;
    if(re <3 || n%2 == 1){
        int t = n/2 + 1;
        ans = 0;
        path[1] = t;//path.push_back(j);
        used[t]  = 1;
        place(t,1);
 
    }
    if( n% 2 == 1)
        result += re + ans;
    else
        result += re;
}
 
int main()
{
    fin>>n;
    work(n);
    fout<< result<<endl;
    return 0;
 
}

原始博客地址: http://www.fuxiang90.com/2012/07/usaco1-5-checker-challenge/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章