题目大意:n个人站成排打架,只有相邻两个人能打,其他不能,最后打剩一个人,问几个可能的赢家的最大值。
思路如下:跟上一题差不多,只是不用排成人链,就有个简单的方法,就是建一个长度为n+2的数组,第0位跟第n+1位不放人,只要中间哪个人能跟第0位与第n+1位同时相邻就可以了。dp[i][j]表示能否相邻,能则1,不能则0。
状态转移方程:dp[i][j]=((dp[i][k]==1 && dp[k][j]==1)?1:0);(i<k<j)这是状态转移方程。。。吧,毕竟这题我是用递归写的,记忆化搜索。当dp[0][k]==1 && dp[k][n+1]同时成立时,这k就是可能获胜的人之一。
AC代码:
import java.util.Scanner;
public class Main//基本跟上一题一样,除了dp数组跟a数组的初始化
{
static Scanner scan=new Scanner(System.in);
public static int winner(int L, int R, int[][] dp, int[][] f)
{
if(dp[L][R]!=-1)
return dp[L][R];
if(L+1==R)
return 1;
int flag=0;
for(int i=L+1;i<R;i++)
if((f[L][i]==1 || f[R][i]==1) && winner(L, i, dp, f)==1 && winner(i, R, dp, f)==1)
{
flag=1;
break;
}
return dp[L][R]=flag;
}
public static void main(String[] args)
{
int t=scan.nextInt();
int cas=0;
while((cas++)<t)
{
int n=scan.nextInt();
int a[]=new int[n+2];
int f[][]=new int[n+2][n+2];
int dp[][]=new int[n+2][n+2];
for(int i=1;i<n+1;i++)
a[i]=scan.nextInt();
for(int i=1;i<n+1;i++)
for(int j=1;j<n+1;j++)
f[i][j]=scan.nextInt();
for(int i=0;i<n+2;i++)
for(int j=0;j<n+2;j++)
dp[i][j]=-1;
int ans=0;
for(int i=1;i<n+1;i++)
if(winner(0, i, dp, f)==1 && winner(i, n+1, dp, f)==1)
ans=Math.max(a[i], ans);
System.out.println("Case "+cas+": "+ans);
}
}
}