蓝桥杯 2015年 第六届 垒骰子(JAVA)
蓝桥杯 2015年 第六届 垒骰子(JAVA)
方法一:简单的dfs思路,只能得30%的分。
需要注意的是:除第一层外底层筛子都有四个面可选,所以diceNum==n时ans要+4,
并且第一层也有四个面可选,所以最后要乘以4
实际最多算到n==12左右, 再往后就极慢了
package provincial_2015B;
import java.util.Scanner;
public class Nine {
private static int[] dice;
private static int[][] exclusion;
private static int n;
private static int ans = 0;
static {
dice = new int[6+1];
dice[1] = 4;
dice[2] = 5;
dice[3] = 6;
dice[4] = 2;
dice[5] = 2;
dice[6] = 3;
exclusion = new int[6+1][6+1];
}
private static void dfs(int up, int diceNum) {
if(diceNum == n) {
ans += 4;
return ;
}
for(int nextUp = 1; nextUp < 7; nextUp++) {
if(exclusion[nextUp][dice[up]]==1)
continue;
dfs(nextUp, diceNum+1);
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
int m = scan.nextInt();
for(int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
exclusion[a][b] = 1;
exclusion[b][a] = 1;
}
for(int i = 1; i < 7; i++) {
dfs(i, 1);
}
System.out.println(ans*4);
}
}
方法二: 动态规划之记忆型递归
比第一种快的多, 可以在之前那个算法算12的时间下算到70, 但还是达不到60%的数据
package provincial_2015B;
import java.util.Arrays;
import java.util.Scanner;
public class Nine {
private static int[] dice;
private static int[][] exclusion;
private static int n;
// private static int ans = 0;
private static int[][] visited;
static {
dice = new int[6+1];
dice[1] = 4;
dice[2] = 5;
dice[3] = 6;
dice[4] = 2;
dice[5] = 2;
dice[6] = 3;
exclusion = new int[6+1][6+1];
}
// private static void dfs(int up, int diceNum) {
// if(diceNum == n) {
// ans += 4;
// return ;
// }
//
// for(int nextUp = 1; nextUp < 7; nextUp++) {
// if(exclusion[nextUp][dice[up]]==1)
// continue;
// dfs(nextUp, diceNum+1);
// }
// }
private static int dp(int up, int diceNum) {
if(diceNum == n) {
return 4;
}
if(visited[up][diceNum]!=0)
return visited[up][diceNum];
int ans = 0;
for(int nextUp = 1; nextUp < 7; nextUp++) {
if(exclusion[nextUp][dice[up]]==1)
continue;
ans += dp(nextUp, diceNum+1);
}
visited[up][diceNum] = ans;
return ans;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
int m = scan.nextInt();
for(int i = 0; i < m; i++) {
int a = scan.nextInt();
int b = scan.nextInt();
exclusion[a][b] = 1;
exclusion[b][a] = 1;
}
visited = new int[6+1][n+1];
int ans = 0;
for(int i = 1; i < 7; i++) {
ans += 4*dp(i, 1);
}
System.out.println(ans);
}
}
方法三: 标准动态规划
比之前得都快很多, 能跑出来80%
package provincial_2015B;
import java.util.Scanner;
public class Nine_case2 {
private static int[] dice;
private static int[][] conflict;
private static int MOD = 1000000007;
static {
dice = new int[6+1];
dice[1] = 4;
dice[2] = 5;
dice[3] = 6;
dice[4] = 2;
dice[5] = 2;
dice[6] = 3;
conflict = new int[6+1][6+1];
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
for(int i = 0; i < m; i++) {
int a=scan.nextInt();
int b=scan.nextInt();
conflict[a][b]=1;
conflict[b][a]=1;
}
int[][] dp = new int[n+1][6+1];
for(int i = 0; i < 6+1; i++)
dp[0][i]=1;
for(int i = 1; i < n; i++) {
for(int j = 1; j < 7; j++) {
for(int k = 1; k < 7; k++) {
if(conflict[dice[j]][k]==1)
continue;
dp[i][j]=
(dp[i][j]+dp[i-1][k])%MOD;
}
}
}
long ans=0;
for(int i = 1; i < 7; i++)
ans=(ans+dp[n-1][i])%MOD;
System.out.println(ans*4*4);
}
}
终极方法: 矩阵快速幂
顺便科普快速幂运算
public static long quickPower(int a, int b, int mod) {
// a^b % MOD
// 任何数对1取模得0
if(mod==1) return 0;
long ans = 1;
while(b!=0) {
if((b&1)==1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
// 待补充...
...