Fight Club
来源:互联网 发布:51单片机串口程序 编辑:程序博客网 时间:2024/04/28 05:40
搏击俱乐部~ 还是黑书上的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; }
- Fight Club
- fight club
- 看完fight club
- Sicily 1822. Fight Club
- Sicily 1822. Fight Club
- 格斗俱乐部 (Fight Club) 1999
- 【动态规划 变形】fight club
- sicily1822 Fight club(dp)
- SOJ 1822. Fight Club(区间DP)
- Sicily oj 1822. Fight Club(区间dp)
- Serendipity, fight club与2002年的第一场雪
- soj 1822 Fight Club(dp,黑书dp例三)
- fight
- Fight
- fight
- 酒吧Club
- health club
- rycbar.club
- SEAndroid概述
- RQNOJ 合唱队形
- SQL 性能调优 笔记
- 设计模式-建造者模式
- 12306分析
- Fight Club
- Struts2— Result与ResultType
- 黑马程序员_银行调度系统
- PHP性能常用检测
- forward与redirect的区别
- 12306分析(2)
- poj2411 状态压缩~方案数
- 也说说ELF
- ThreadLocal与多线程