Fight Club

搏击俱乐部~  还是黑书上的DP啦

 

题意初看有点像约瑟夫环,n个人逆时针站成一圈,从一个人开始,与其右边的人决斗,输了的就退出圈,问最后n个人中,哪些人有可能留到最后~

问题转化一下,就是将第i个人处,将圈展开,两端都是i,看是否存在一点k,使两端的i可以相互到达;如果可以相互到达,则说明第i个人有可能会赢

 

dp[i][k] 表示i和k是否可以到达

dp[i][j] 可以到达的条件是:

存在一点k(i<k<j)使dp[i][k]  以及  dp[k][j] 都可到达,并且第i个人和第k个人决斗会赢,或者第j个人和第k个人决斗会赢;

这个地方我纠结了很久,为什么要这样判断啊?

因为只有在第i个人与第k个人决斗会赢时,才能保证第i个人与第j个人的决斗结果可以由本身决斗两人的结果所决定~不然,如果第k个人可以赢第i个人,那么即使第i个人本身可

以赢第j个人,也最后也不能保证第i个人可以赢第j个人。

 

另外,因为成的是一个环,要将其展开,所以ij要一直更新到2*n。。。

 

代码:

 

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[150][150];
int a[50][50];
int main(){
    int m;
    cin>>m;
    while(m--){
          int n;
          cin>>n;
          for(int i=1;i<=n;i++){
                  for(int j=1;j<=n;j++){
                          cin>>a[i][j];
                  }
          }           
          memset(dp,0,sizeof(dp));
          for(int i=1;i<=n*2;i++)
                  dp[i][i+1]=1;
          for(int i=2;i<=n*2;i++){
                  for(int j=1;j<=(2*n-i);j++){
                          int k=i+j;
                          for(int g=j+1;g<=k-1;g++){
                                 if((dp[j][g]==1)&&(dp[g][k]==1)){
                                         int temp1=j>n?j-n:j;
                                         int temp2=g>n?g-n:g;
                                         int temp3=k>n?k-n:k;
                                         if((a[temp1][temp2]==1)||a[temp3][temp2]==1){
                                                dp[j][k]=1;
                                                break;
                                         }
                                 }  
                          }
                  }
          }
          for(int i=1;i<=n;i++){
                      cout<<dp[i][i+n]<<endl;
          }  
          cout<<endl;
    }
    return 0; 
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值