题目1:二维数组(N*N),沿对角线方向,从右上角打印到左下角:
- { 1 2 3 4 }
- { 5 6 7 8 }
- { 9 10 11 12 }
- {13 14 15 16 }
- 4
- 3 8
- 2 7 12
- 1 6 11 16
- 5 10 15
- 9 14
- 13
public class Main {
private static final int[][] DATA = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
public static void main(String[] args) {int n = 4;int i_data = 0;int j_data = n-1;while(i_data != n) {for(int i=i_data,j=j_data;i<=n-1&&j<=n-1;i++,j++)System.out.print(DATA[i][j]+" ");System.out.println();if(j_data>0)j_data--;elsei_data++;}}
}
题目2:在一个桌子上放了若干个数值不等的红包,围成一个圈,现在让你选取若干个红包,要求相邻的两个红包不能同时选取,编程求出选取红包所得
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
const int MAXN = 22;
int arr[MAXN];
int n;
int newMethod(int start,int end,int signal){
int temp1=0,temp2=0;
if(start - end > 0)
return 0;
if(start-end == 0)
return arr[start];
if(signal == 0){
temp1 = newMethod(start+2,end-1,1)+arr[start];
temp2 = newMethod(start+1,end,1);
}
else{
temp1 = newMethod(start+2,end,1)+arr[start];
temp2 = newMethod(start+1,end,1);
}
if(temp1>temp2)
return temp1;
else
return temp2;
}
int main()
{
int T;
cin>>T;
while(T--)
{
n = 0;
cin>>arr[n++];
while(cin.get() == ',')
cin>>arr[n++];
int newMax = newMethod(0,n-1,0);
printf("%d\n", newMax);
}
return 0;
}
动态规划解决该问题:
从某个红包按顺时针依次选取,则每个位置都有两种状态,选取和不选取,最终要使利益最大化,可以用动态规划来解决。在动态规划中,每一步的选择都是前面所有步骤的总结,每一步选择最优从而使最终方案最优。DP算法的这种本质决定了问题必须是线性结构,但本问题是环状结构,第一个红包(指逻辑上的第一个,环上的任何一个红包都可以作为第一个)的状态不仅影响第二个红包的状态,还影响最后一个红包的状态,所以首先要将环状结构转化为线性结构。转化方法:将所有选取方案分为两类,第一类是选取第一个红包的所有方案,第二类是不选取第一个红包的所有方案。对于第一类,选取第一个红包,从而第二个红包和最后一个红包都不能选取,剩余红包的状态不确定;对于第二类,不选取第一个红包,那么剩下的红包状态都不确定。将环状结构转化为线性结构可以使问题简化,逻辑更加清晰,顺序选取的过程中,每个红包的状态只取决与它前面一个红包,从而可以使用DP来求解。
第二步是分别对两类中不确定的红包运用动态规划。若某个位置的红包选取,那么其后一位置的红包不能选取;若某一位置的红包未选取,其后一位置的红包可以选取,也可以不选取。DP转移方程:
dp[i+1][0]=max(dp[i][0],dp[i][1])
dp[i+1][1]=dp[i][0]
其中i表示红包的索引,第二维中的0表示不取红包i,1表示选取红包i,也就是说第二维用来表示红包的两种状态;而dp[i][0]表示从红包0到红包i中选取红包,并且不选红包i,获得的红包最大值;dp[i][1]表示从红包0到红包i中选取红包,并且选取红包i,所获得的红包最大值。
算法时间复杂度为O(n),源代码: