提交 65022e10 编写于 作者: qq_36480062's avatar qq_36480062

commit

上级 ebed102d
package com.shiyu;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
import java.util.PriorityQueue;
public class tsdt {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<Integer> jishu = new ArrayList<Integer>();
ArrayList<Integer> oshu = new ArrayList<Integer>();
Iterator<Integer> iterator = jishu.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
System.out.println(next);
}
while (sc.hasNext()) {
int a = sc.nextInt();
if (a == 1111)
break;
if (a % 2 == 0) {
oshu.add(a);
} else {
jishu.add(a);
}
}
System.out.println(jishu);
System.out.println(oshu);
System.out.println(isPalindrome(121));
PriorityQueue<Integer> a = new PriorityQueue<Integer>();
a.add(6);
a.add(5);
System.out.println(a.poll());
}
public static boolean isPalindrome(int x) {
return new StringBuilder(x + "").reverse().toString().equals(Integer.toString(x));
}
}
......@@ -131,7 +131,6 @@ public class 打家劫舍 {
int[] dp = new int[n + 1];
dp[1] = nums[0];
for (int i = 2; i <= n; ++i) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i - 1]);
}// dp[i] 表示抢到第 i 个房子可以获得的最大值
......
package dp;
import java.util.Scanner;
/**
* Robot
* Time Limit:4000MS     Memory Limit:102400KB     64bit IO Format:%I64d & %I64u
* Submit
* Status
* Description
* Michael has a telecontrol robot. One day he put the robot on a loop with n cells. The cells are numbered from 1 to n clockwise. 
* At first the robot is in cell 1. Then Michael uses a remote control to send m commands to the robot. A command will make the robot walk some distance. Unfortunately the direction part on the remote control is broken, so for every command the robot will chose a direction(clockwise or anticlockwise) randomly with equal possibility, and then walk w cells forward. 
* Michael wants to know the possibility of the robot stopping in the cell that cell number >= l and <= r after m commands. 
* Input
* There are multiple test cases. 
* Each test case contains several lines. 
* The first line contains four integers: above mentioned n(1≤n≤200) ,m(0≤m≤1,000,000),l,r(1≤l≤r≤n). 
* Then m lines follow, each representing a command. A command is a integer w(1≤w≤100) representing the cell length the robot will walk for this command.   
* The input end with n=0,m=0,l=0,r=0. You should not process this test case. 
* Output
* For each test case in the input, you should output a line with the expected possibility. Output should be round to 4 digits after decimal points.
* Sample Input
* 3 1 1 2
* 1
* 5 2 4 4
* 1
* 2
* 0 0 0 0
* Sample Output
* 0.5000
* 0.2500
* 有标记着1~n的环,初始时有个机器人在1的位置,有m个操作,每个操作是使机器人随机的顺时针或逆时针的走w步,求所有操作过后机器人停在区间[l,r]内的概率;
* 思路:挺明显的概率dp,首先可以很直观的定义出状态dp[i][j],表示第j次操作后停留在第i位置的概率,转移方程是
* dp[(i + w) % n][j] = dp[i[j-1] * 0.5;
* dp[i-w][j]=dp[i][j-1]*0.5;其中i-w不断的加n使它大于等于0;
* 但是题目操作数比较大,这样会超内存,观察发现每次转移只和上一次操作有关,所以可以用个滚动数组来节省空间;优化空间后转移方程是
* dp[(i + w) % n][j&1] += dp[i][!(j&1)] * 0.5;
* dp[x][j&1] += dp[i][!(j&1)] * 0.5;x=i-w,x也要叠加到非负;
* 最后答案就是所有操作完后,位置l到r的概率总和。
* #include <iostream>
* #include <cstdio>
* #include <cstring>
* #include <algorithm>
* #include <cmath>
* #include <vector>
* using namespace std;
* const int N = 2100;
* const int inf = 0x3f3f3f3f;
* double dp[N][2];
* int main()
* {
*     int n, m, l, r;
*     while(scanf("%d %d %d %d", &n, &m, &l, &r)!=EOF)
*     {
*         if(n==0 && m==0 && l==0 && r==0)
*             break;
*         for(int i=1;i<=n;i++)
*             dp[i][1]=dp[i][0]=0;
*         dp[1][0]=1;
*         for(int i=1;i<=m;i++)
*         {
*             int k;
*             scanf("%d", &k);
*             for(int j=1;j<=n;j++)
*             {
*                 int x=(j+k)%n, y=(j-k);
*                 while(y < 0)
*                     y += n;
*                 if(x==0) x=n;
*                 if(y==0) y=n;
*                 dp[x][i&1]+=dp[j][!(i&1)]*0.5;
*                 dp[y][i&1]+=dp[j][!(i&1)]*0.5;
*             }
*             for(int j=1;j<=n;j++)
*                 dp[j][!(i&1)]=0;
*         }
*         double sum=0;
*         for(int i=l;i<=r;i++)
*         {
*             sum+=dp[i][m&1];
*         }
*         printf("%.4f\n",sum);
*     }
*     return 0;
* }
*/
public class 机器人概率走 {
public static void main(String[] args) {
int n = 0, m = 0, l = 0, r = 0;
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
l = sc.nextInt();
r = sc.nextInt();
if (n == 0 && m == 0 && l == 0 && r == 0)
System.out.println(0);
}
}
package dp;
import java.util.Arrays;
/**
* LeetCode 第 256 号问题:粉刷房子,非常精妙,
* https://mp.weixin.qq.com/s?__biz=MzUyNjQxNjYyMg==&mid=2247486936&idx=1&sn=27ec53c1463384edeeee138db23c1c7d&chksm=fa0e6259cd79eb4f240786ad7c00dcd0ed39ad68fd62b72e15d6a8ee0ecbd26b6250ab3b1171&scene=21#wechat_redirect
......@@ -15,30 +17,52 @@ package dp;
*/
public class 粉刷房子 {
public static void main(String[] args) {
int[][] arr={{17,2,17},{16,16,5},{14,3,19}};
int[][] arr = {{17, 2, 17}, {16, 16, 5}, {14, 3, 19}};
System.out.println(Fen(arr));
int[][] arrr = {{17, 2, 17, 4, 6}, {16, 2, 5, 16, 1}, {14, 11, 12, 15, 4}};
System.out.println(S(arrr));//4,1,4
System.out.println(minCostII(arrr));////4,1,4
int[] ran = LIS.random(23);
System.out.println(Arrays.toString(ran));
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
int minIndex = -1;
for (int l = 0; l < ran.length; ++l) {
if (min1 > ran[l]) {
min2 = min1;//如果最小的那个元素在数组末尾,会导致min2,不是次最小元素,所以这么写
min1 = ran[l];
minIndex = l;
} else if (min2 > ran[l]) {
min2 = ran[l];
}
}
System.out.println("---");
System.out.println(min1);
System.out.println(min2);
System.out.println(minIndex);
Arrays.sort(ran);
System.out.println(Arrays.toString(ran));
}
public static int[][] dp;
/**
* 问题拆解
* <p>
* 对于每个房子来说,都可以使用三种油漆当中的一种,如果说不需要保证相邻的房子的颜色必须不同,
* 那么整个题目会变得非常简单,每个房子直接用最便宜的油漆刷就好了,但是加上这个限制条件,
* 你会发现刷第 i 个房子的花费其实是和前面 i - 1 个房子的花费以及选择相关,如果说我们需要知道第 i 个房子使用第 k 种油漆的最小花费,
* 那么你其实可以思考第 i - 1 个房子如果不用该油漆的最小花费,这个最小花费是考虑从 0 到当前位置所有的房子的。
* 状态定义
* <p>
* 通过之前的问题拆解步骤,状态可以定义成 dp[i][k],表示如果第 i 个房子选择第 k 个颜色,
* 那么从 0 到 i 个房子的最小花费
* 递推方程
* <p>
* 基于之前的状态定义,以及相邻的房子不能使用相同的油漆,那么递推方程可以表示成:
* <p>
* dp[i][k] = Math.min(dp[i - 1][l], ..., dp[i - 1][r]) + costs[i][k], l != k, r != k
* 实现
* <p>
* 因为我们要考虑 i - 1 的情况,但是第 0 个房子并不存在 i - 1 的情况,因此我们可以把第 0 个房子的最小花费存在状态数组中,当然你也可以多开一格 dp 状态,其实都是一样的。
* 对于这道题目,你可能会问这不是和矩阵类动态规划类似吗?
* 如果单从房子来考虑的确是,但是对于颜色的话,我们必须考虑考虑相邻房子的所有颜色,这就有点序列的意思在里面了。
......@@ -48,17 +72,134 @@ public class 粉刷房子 {
return 0;
}//没有东西,直接返回0
int n = nums.length;
dp = new int[n][3];
dp = new int[n][3];//由于只有三种油漆,刷第 i 个房子的花费其实是和前面 i - 1 个房子的花费以及选择相关
for (int i = 0; i < nums[0].length; i++) {
dp[0][i] = nums[0][i];
}//先初始化第一行,要理解dp数组语义
for (int i = 1; i < n; i++) {
for (int i = 1; i < n; i++) {//找到最优解,动态规划
dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + nums[i][0];
dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + nums[i][1];
dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + nums[i][2];
}//状态可以定义成 dp[i][k],表示如果第 i 个房子选择第 k 个颜色
return Math.min(dp[n - 1][0], Math.min(dp[n - 1][2], dp[n - 1][1]));//最后的结果选最小的
}
/**
* LeetCode 第 265 号问题:粉刷房子II。
* 假如有一排房子,共 n 个,每个房子可以被粉刷成 k 种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
* 当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x k 的矩阵来表示的。
* 例如,costs[0][0] 表示第 0 号房子粉刷成 0 号颜色的成本花费;costs[1][2] 表示第 1 号房子粉刷成 2 号颜色的成本花费,以此类推。请你计算出粉刷完所有房子最少的花费成本。
* 所有花费均为正整数。
* 示例:
* 输入: [[1,5,3],[2,9,4]]
* 输出: 5
* 解释: 将 0 号房子粉刷成 0 号颜色,1 号房子粉刷成 2 号颜色。最少花费: 1 + 4 = 5;
* 或者将 0 号房子粉刷成 2 号颜色,1 号房子粉刷成 0 号颜色。最少花费: 3 + 2 = 5.
* 进阶:
* 您能否在 O(nk) 的时间复杂度下解决此问题?
* <p>
* 现在有k种油漆,
* 对于第 i 个房子的每种颜色,我们对比看第 i - 1 个房子的 k 种油漆,找到不相重的最小值就好,但是这里的时间复杂度是 O(n*k^2)。
* 其实这是可以优化的,我们只需要在第 i - 1 个位置的状态中找到最大值和次大值,在选择第 i 个房子的颜色的时候,
* 我们看当前颜色是不是和最大值的颜色相重,不是的话直接加上最大值,如果相重的话,我们就加上次大值,这样一来,
* 我们把两个嵌套的循环,拆开成两个平行的循环,时间复杂度降至 O(n*k)。
* dp数组语义不变
*
* @param costs
* @return
*/
public static int S(int[][] costs) {
if (costs.length == 0 || costs[0].length == 0) {
return 0;
}//合法性判断
int n = costs.length, k = costs[0].length;
int[][] dp = new int[n][k];
for (int i = 1; i < n; ++i) {
Arrays.fill(dp[i], Integer.MAX_VALUE);
}//初始化
for (int i = 0; i < k; ++i) {
dp[0][i] = costs[0][i];
}//把油漆第一行的元素,赋值给dp数组第一行
{//算法精髓
for (int i = 1; i < n; ++i) {//行数
for (int j = 0; j < k; ++j) {//列数
for (int m = 0; m < k; ++m) {//寻找与前一个房子不同的k
if (m != j) {//,这里只要保持列数不同,就能保证不同颜色
dp[i][m] = Math.min(dp[i][m], dp[i - 1][j] + costs[i][m]);//寻找与上一个房子不同颜色的最小的那个颜色
}
}
}
}
}
int result = Integer.MAX_VALUE;
for (int i = 0; i < k; ++i) {
result = Math.min(result, dp[n - 1][i]);//最后的结果,从所有的颜色中找出最小的花费
}
return Math.min(dp[n - 1][0], Math.min(dp[n - 1][2], dp[n - 1][1]));
return result;
}
/**
* 最优版本LeetCode 第 265 号问题:粉刷房子II。
* O(n*k)
*
* @param costs
* @return
*/
public static int minCostII(int[][] costs) {
if (costs.length == 0 || costs[0].length == 0) {
return 0;
}//合法性判断
int n = costs.length, k = costs[0].length;
int[][] dp = new int[n][k];
for (int i = 1; i < n; ++i) {
Arrays.fill(dp[i], Integer.MAX_VALUE);
}
for (int i = 0; i < k; ++i) {
dp[0][i] = costs[0][i];
}
{//算法精髓,把三个嵌套的循环拆成两个平行的循环,达到O(n*k)的复杂度
for (int i = 1; i < n; i++) {
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
//min1是这算出来的上面那一排的最小花费,min2是这上面那一排的次最小花费,
//结合dp数组语义
int minIndex = -1;
for (int l = 0; l < k; l++) {
if (min1 > dp[i - 1][l]) {
min2 = min1;//如果最小的那个元素在数组末尾,会导致min2,不是次最小元素,所以这么写
min1 = dp[i - 1][l];//最小元素(花费)算出来
minIndex = l;
} else if (min2 > dp[i - 1][l]) {
min2 = dp[i - 1][l];
}
}//精髓,找出,minIndex代表颜色,是第几列,
for (int j = 0; j < k; j++) {
if (minIndex != j) {
dp[i][j] = Math.min(dp[i][j], min1 + costs[i][j]);
} else {
dp[i][j] = Math.min(dp[i][j], min2 + costs[i][j]);
}
}
}
}
int result = Integer.MAX_VALUE;
for (int i = 0; i < k; ++i) {
result = Math.min(result, dp[n - 1][i]);
}
return result;
}
}
package dp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;
/**
* FatMouse's Speed
* Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
* Total Submission(s): 9174    Accepted Submission(s): 4061
* Special Judge
* <p>
* Problem Description
* FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the speeds are decreasing.
*  
* <p>
* Input
* Input contains data for a bunch of mice, one mouse per line, terminated by end of file.
* <p>
* The data for a particular mouse will consist of a pair of integers: the first representing its size in grams and the second representing its speed in centimeters per second. Both integers are between 1 and 10000. The data in each test case will contain information for at most 1000 mice.
* <p>
* Two mice may have the same weight, the same speed, or even the same weight and speed.
*  
* <p>
* Output
* Your program should output a sequence of lines of data; the first line should contain a number n; the remaining n lines should each contain a single positive integer (each one representing a mouse). If these n integers are m[1], m[2],..., m[n] then it must be the case that
* <p>
* W[m[1]] < W[m[2]] < ... < W[m[n]]
* <p>
* and
* <p>
* S[m[1]] > S[m[2]] > ... > S[m[n]]
* <p>
* In order for the answer to be correct, n should be as large as possible.
* All inequalities are strict: weights must be strictly increasing, and speeds must be strictly decreasing. There may be many correct outputs for a given input, your program only needs to find one.
*  
* <p>
* Sample Input
* 6008 1300 老鼠重量, 老鼠速度
* 6000 2100
* 500 2000
* 1000 4000
* 1100 3000
* 6000 2000
* 8000 1400
* 6000 1200
* 2000 1900
*  
* <p>
* Sample Output
* 4 4 5 9 7
* 需要从输入的数据中找出一组数据,满足老鼠的重量增大,而老鼠的速度递减
* <p>
* 这题是一道简单的DP题,是dp中叫最长有序子序列的问题。和数塔类似。
* 先将重量从小到大排,再找速度的最长递减子序列。
* 代码:0MS
* #include <cstdio>
* #include <iostream>
* #include <cstring>
* #include <algorithm>
* using namespace std;
* #define M 2050
* struct node {
* int w,s,index; //w:重量,s:速度,index:第几个数。
* }map[M];
* bool cmp(node x,node y){ //如果重量相等,速度大的排前面。
*  if(x.w==y.w)
* return x.s>y.s;
* return x.w<y.w; //如果重量不相等,重量小的排前面。
* }
* int res[M],dp[M],pre[M];
* int main()
* {
* int i=1,j,k,n,m,maxlen;
* while(cin>>n>>m)
* {
* map[i].w=n;map[i].s=m;map[i].index=i;
* dp[i]=1;pre[i]=0;
* i++; //这道题输入有点问题,要强制结束才有输出。
* }
* sort(map+1,map+i,cmp); //对数据进行排序。
* n=i-1;maxlen=0; //n表示元素的个数。maxlen表示当前的最长的长度。
* int maxi; //maxi记录最长递减子序列的末元素。
* dp[1]=1;
* for(i=1;i<=n;i++) //模板。
* for(j=1;j<i;j++)
* if(map[i].w>map[j].w && map[i].s<map[j].s && dp[j]+1>dp[i]) //发现以i结束的有更长的就更新。
* {
* dp[i]=dp[j]+1;
* pre[i]=j; //pre[]记录的就是i元素的前一个元素是j。
* if(dp[i]>maxlen) //判断是否比最长个还长。
* {
* maxi=i;
* maxlen=dp[i];
* }
* }
* int t=maxi;
* i=0;
* while(t!=0) //通过回溯将元素反序输入res[],同时i找到了元素的个数。
* {
* res[i++]=t;
* t=pre[t];
* }
* printf("%d\n",i);
* while(i>0)
* {
* i--; //正序输出。
* printf("%d\n",map[res[i]].index);
* }
* return 0;
* }
*/
public class 胖老鼠 {
private static class mouse {
public int Weight;
public int Speed;
public int num;//编号
public mouse(int weight, int speed, int num) {
Weight = weight;
Speed = speed;
this.num = num;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<mouse> list = new ArrayList<mouse>();
int num = 1;
while (sc.hasNext()) {
list.add(new mouse(sc.nextInt(), sc.nextInt(), num++));
}
Collections.sort(list, new Comparator<mouse>() {
@Override
public int compare(mouse x, mouse y) {
if (x.Weight == y.Weight)
return x.Speed - y.Speed;
return x.Weight - y.Weight;
}//排列
});
int[] dp = new int[list.size() + 1];
ArrayList<Integer> mem = new ArrayList<Integer>();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册