SPOJ 196 动态规划

题意:黑书P117 决斗  

分析:假设需要判断x是否能赢得整场战斗,把环看成链,x点拆成两个,那么编号为x的人能从中胜出的充分必要条件是他能与自己“相遇”。

这样,在连续几个人的链中,只须考虑头尾两个人能否胜利会师,中间的则不予考虑。

设meet[i][j]记录i和j能相遇,能则为true,否则为false,则问题转化为了是否能找到一个k,使得i 和 k, k和j均能相遇,而 i或j能打败k。

 

 

const int M = 202;
int n;
int a[M][M], meet[M][M];

void readData(){
    cin>>n; char c;
    FOE(i, 1, n){
        cin.get(c);
        FOE(j, 1, n){
            cin.get(c);
            a[i][j]=c-'0';
        }
    }
    memset(meet,0,sizeof meet);
    FOR(i, 1, n<<1) meet[i][i+1]=1;
}

void d(int i,int j){
    if(meet[i][j]) return;
    FOR(k, i+1, j) {
        int ii=(i-1)%n+1, jj=(j-1)%n+1, kk=(k-1)%n+1;
        if(a[ii][kk] || a[jj][kk]) {
            d(i,k); d(k,j);
            if(meet[i][k]==1&&meet[k][j]==1) {
                meet[i][j]=1;
                return;
            }
        }
    }
    meet[i][j]=-1;
}

void solve(){
    int cnt=0;
    FOE(i, 1, n) {
        d(i,i+n);
        if(meet[i][i+n]==1) cnt++;
    }
    cout<<cnt<<endl;
    FOE(i, 1, n)
        if(meet[i][i+n]==1)
            cout<<i<<endl;
}

int main(){
    int t; cin>>t;
    while(t--) {
        readData();
        solve();
    }
    return 0;
}

 

posted @ 2013-06-19 12:29  心向往之  阅读(179)  评论(0编辑  收藏  举报