SPOJ 196 Musketeers(JAVA版)
来源:互联网 发布:如何重启linux服务器 编辑:程序博客网 时间:2024/05/19 02:45
SPOJ 196 Musketeers
題目大意:有n个人要进行n-1场决斗,最后只能有一个人存活,决斗可以从这n个人任意一个开始,但是只有相邻的两个人能进行决斗,问最后哪些人有可能活下来,输出人数,并把他们的序号从小到大输出。
思路如下:因为这n个人排成一个圈,任意相邻两个人可以进行决斗(最后一个人可以和第一个人决斗,一个圈),于是先用n+1长度的数组构造一个“人链”,数组的开头和结尾是同一个人比如:有5个人,先从第一个人开始看,1站排头,即a0,a1,a2,a3,a4,a5分别是1,2,3,4,5,1。每有一个人死亡,那个人就退场,直到最后,如果能够首尾相邻那就表示那个人能够获胜。考虑获胜前最后一个状态便可。即第k个人,可以被排头的人打败或者被排尾的人打败,并且最后会剩下三个人(排头,k,排尾)。如此排头(即排尾)的这个人就能获胜,这就知道是dp了。
dp[i][j]表示第 i 人与第 j 人能否相遇,能为1,否为0;a[i]表示人链中排第 i 的人;f[i][j]用来记录题目中的数组。
动态转移方程:dp[i][j]=(((f[a[i]][a[k]] || f[a[j]][a[k]]) && dp[i][k] && dp[k][j])?1:0);(i<k<j)
这里附上两份代码,因为第一次做是用递归(记忆化搜索)做的,后来想想,因为习惯,改成了循环。
AC代码:(循环)
import java.util.Scanner;public class Main{static Scanner scan=new Scanner(System.in);public static void main(String[] args){int t=scan.nextInt();while(t-->0){int n=scan.nextInt();int f[][]=new int[n+1][n+1];String str=scan.nextLine();for(int i=1;i<n+1;i++){str=scan.nextLine();for(int j=1;j<n+1;j++)f[i][j]=str.charAt(j-1)-48;}int dp[][]=new int[n+1][n+1];int a[]=new int[n+1];int ans[]=new int[n+1];//这个数组用来记录获胜的人int cas=0;for(int len=1;len<n+1;len++)//len表示第len个人在排头(考察他是否能胜出){int meet=len;for(int k=0;k<n+1;k++)//这个循环构造人链{if(meet<=n)a[k]=meet;elsea[k]=meet-n;meet++;}for(int i=1;i<n+1;i++)for(int j=0;j+i<n+1;j++){if(j+1==j+i)//如果左右相邻,直接就是能两人能相遇dp[j][j+i]=1;else{for(int k=j+1;k<j+i;k++)//找人if((f[a[j]][a[k]]==1 || f[a[j+i]][a[k]]==1) && dp[j][k]==1 && dp[k][j+i]==1){dp[j][j+i]=1;break;}//满足条件就赋1,然后breakelse dp[j][j+i]=0;//因为这个数组要用很多次,所以找不到还是赋0}}if(dp[0][n]==1)//相遇了ans[cas++]=len;//记}System.out.println(cas);for(int i=0;i<cas;i++)System.out.println(ans[i]);}}}AC代码:(递归)
import java.util.Scanner;public class Main//标注的地方是跟循环不一样的地方{static Scanner scan=new Scanner(System.in);public static int winner(int L, int R, int[] a, int[][] dp, int[][] f){if(dp[L][R]!=-1)//记忆化搜索,看看是否检查过return dp[L][R];if(L+1==R)return dp[L][R]=1;int flag=0;for(int i=L+1;i<R;i++)if((f[a[L]][a[i]]==1 || f[a[R]][a[i]]==1) && winner(L, i, a, dp, f)==1 && winner(i, R, a, dp, f)==1){flag=1;break;}return dp[L][R]=flag;}public static void main(String[] args){int t=scan.nextInt();while(t-->0){int n=scan.nextInt();int f[][]=new int[n+1][n+1];String str=scan.nextLine();for(int i=1;i<n+1;i++){str=scan.nextLine();for(int j=1;j<n+1;j++)f[i][j]=str.charAt(j-1)-48;}int dp[][]=new int[n+1][n+1];int a[]=new int[n+1];int ans[]=new int[n+1];int cas=0;for(int i=1;i<n+1;i++){for(int x=0;x<n+1;x++)for(int y=0;y<n+1;y++)dp[x][y]=-1;//初始化,每进一次循环初始化一次,全部为-1,因为未检查(这个地方在记忆化搜索起作用)int meet=i;//构造人链for(int j=0;j<n+1;j++){if(meet<=n)a[j]=meet;elsea[j]=meet-n;meet++;}if(winner(0, n, a, dp, f)==1)//0与n能否相遇,即首尾ans[cas++]=i;}System.out.println(cas);for(int i=0;i<cas;i++)System.out.println(ans[i]);}}}
0 0
- SPOJ 196 Musketeers(JAVA版)
- SPOJ 196 Musketeers(区间DP)
- SPOJ 196 MUSKET - Musketeers 火枪手 环类问题
- SPOJ 345 Mixtures(JAVA版)
- SPOJ0196 musketeers
- 决斗 dp, spoj196 Musketeers
- Bear and Three Musketeers
- Bear and Three Musketeers
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- SPOJ
- 【深度学习】资料搜集
- make: *** cpu/arm920t/s3c24X0/: 没有那个文件或目录。 停止。 (uboot)
- java keytool 使用总结
- linux shell之sed
- 一步,一心。
- SPOJ 196 Musketeers(JAVA版)
- Linux内存管理中的分段和分页技术
- Toast 多次创建显示问题
- ls 命令详解
- 管理
- arcgis 中使用sde数据库 发布服务后 不刷新的问题
- 简单的ajax实现局部刷新
- 自定义uibutton 如何去除原有title
- 开发框架——横版格斗——2.关键帧动画导入与切割