3 n 2 3n^2 3n2 +10n = O( n 2 n^2 n2)
n 2 n^2 n2 / 10 + 2 n 2^n 2n = O( 2 n 2^n 2n)
21 + 1 / n = O(1)
log n 3 n^3 n3 = O(logn)
10log 3 n 3^n 3n = O(n)
题目:假设某算法在输入规模为n时的计算时间为T=3*2n(2的n的次方).在某台计算机上实现并完成该算法在t秒.现有另一台计算机,其运行速度为第一台的64倍,那么在这台新机器上用同一算法在t秒内能解输入输入规模为多大的问题?
T(n) = n 2 n^2 n2
T(n) = 8
题目:一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如,第6页用数字6表示,而不是06或006等。对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1,2,…,9。
看不懂上面的可以通过代码理解:老师的代码。
#include
#include
#include
long num;
long tab1[10] = {0, 1, 20, 300, 4000, 50000, 600000, 7000000, 80000000, 900000000};
long tab2[10] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
long result[10];
int flag = 0;
void compute (long x)
{
int len, i, high;
long y;
char string[10];
sprintf(string,"%d",x);
//len = strlen (itoa(x, string, 10));
len = strlen (string);
high = string[0] - 48;
if (len == 1)
{
for (i = 0; i <= x; i++)
{
result[i] += tab1[len];
}
if (flag == 0)
{
result[0] -= tab2[len];
}
return;
}
else
{
for (i = 0; i <= 9; i++)
{
result[i] += tab1[len - 1]*high;
}
if (flag == 0)
{
for (i = 1; i < len; i++)
{
result[0] -= tab2[len - i];
}
//flag = 1;
}
for (i = 0; i < high; i++)
{
result[i] += tab2[len];
}
if (flag == 0)
{
result[0] -= tab2[len];
flag = 1;
}
for (i = 1; string[i] == 48 && len - i > 1; i++)
result[0]++;
y = x - high*tab2[len];
result[high] += (y + 1);
compute (y);
}
}
int main ()
{
int i;
//freopen ("count.in", "r", stdin);
//freopen ("count.out", "w", stdout);
scanf ("%ld", &num);
compute (num);
for (i = 0; i<10; i++)
{
printf ("%ld\n", result[i]);
}
return 0;
}
#include
#include
#include
long num;
long tab1[10] = {0, 1, 20, 300, 4000, 50000, 600000, 7000000, 80000000, 900000000};
long tab2[10] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
long result[10];
void compute (long x)
{
int len, i, high;
long y;
char string[10];
sprintf(string,"%d",x);
len = strlen (string);
high = string[0] - 48;
if (len == 1) {
for (int i = 0 ; i <= x; i++) {
result[i] += tab1[len];
}
} else {
//1.先加上 high * tab1[len - 1]
for (int i = 0 ; i <= 9; i++) {
result[i] += tab1[len - 1] * high;
}
//2.加上 tab2中的数
for (int i = 0; i < high; i++) {
result[i] += tab2[len];
}
//3.加上y 和x本身的0
for (int i = 1; i < len - 1; i++) {
if (string[i] == '0')result[0]++;
}
y = x - high * tab2[len];
result[high] += y + 1;
compute(y);
}
}
int main ()
{
int i;
scanf ("%ld", &num);
compute (num);
char string[10];
sprintf(string,"%d",num);
int len = strlen (string);
//减去一次多算的的0
for (int i = 1; i < len; i++) {
result[0] -= tab2[i];
}
result[0] -= tab2[len];
for (i = 0; i<10; i++)
{
printf ("%ld\n", result[i]);
}
return 0;
}
void binarySearch(int a[], int n, int x, int &i, int &j) {
int left = 0, r = n - 1;
while (left <= r) {
int mid = (left + r) / 2;
if (x == a[mid]) {
i = j = mid;
return;
} else if (x > a[mid]) {
left = mid + 1;
} else {
r = mid - 1;
}
}
i = r;
j = left;
}
#include
#include
using namespace std;
int n, num;
int main() {
map<int, int> mp;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &num);
mp[num]++;
}
int max = 0;
for (map<int, int>::iterator it = mp.begin(); it != mp.end(); it++) {
if (max < it->second) {
num = it->first;
max = it->second;
}
}
printf("%d\n%d", num, max);
return 0;
}
#include
using namespace std;
int rec[10005];
void set(int n, int cnt) {
rec[cnt] = n;
for (int i = cnt; i >= 0; i--) {
cout << rec[i];
}
cout << endl;
for (int i = 1; i <= n / 2; i++) {
set(i, cnt + 1);
}
}
int main() {
int n;
cin >> n;
set(n, 0);
return 0;
}
for (int len = 2; len <= n; len++) { //区间长度
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
for (int k = 1; k < j; k++) {
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + 第i个矩阵的行*
第k个矩阵的列*第j个矩阵的列); //后面的值就= (pi-1 * pk * pj)
}
}
}
设计dp[i][j] :存储第一个串的前i个字符和第二个串的前j个字符的最长公共子序列的长度
设计c[i][j]: 记录状态是由哪一个子问题得来的。1表示由dp[i-1][j-1]得来,2表示由dp[i - 1][j]得来,3表示由dp[i][j-1]得来。
void LCS(int n, int m, char x[], char y[], int c[][], int dp[][]) {
//初始化
for (int i = 1; i <= n; i++) dp[i][0] = 0;
for (int j = 1; j <= m; j++) dp[0][j] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (x[i] == y[j]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
c[i][j] = 1;
} else if (dp[i - 1][j] >= dp[i][j - 1]) {
dp[i][j] = dp[i - 1][j];
c[i][j] = 2;
} else {
dp[i][j] = dp[i][j - 1];
c[i][j] = 3;
}
}
}
}
设计dp[i]: 代表以a[i]为结尾元素的最长递增子序列长度. 序列a的最长递增子序列的长度就为max{b[i], 0<=i
void LIS(int dp[], int a[], int n) {
dp[0] = 1; //初始化
for (int i = 1; i < n; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (a[i] >= a[j] && dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1;
}
}
}
}
设计dp[i][j]:表示完成i个任务,A机器花费时间为j的条件下B机器花费的最少时间。
#include
#include
#include
using namespace std;
const int N = 1e3 + 5;
int n, a[N], b[N], ans, sum, dp[N][N];
void f() {
memset(dp, 0x3f, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= sum; j++) {
if (j >= a[i]) {
dp[i][j] = min(dp[i - 1][j - a[i]], dp[i - 1][j] + b[i]);
} else {
//只能B机器做
dp[i][j] = dp[i - 1][j] + b[i];
}
}
}
//找出最小的值
ans = 0x3f3f3f3f;
for (int i = 0; i <= sum; i++) {
int t = max(i, dp[n][i]);
ans = min(ans, t);
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i], sum += a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
f();
cout << ans << endl;
return 0;
}
#include
#include
#include
#include
using namespace std;
const int N = 10005;
struct Node {
int s, e;
bool operator < (const Node& w) const {
return s < w.s;
}
}p[N];
int n;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d%d", &p[i].s, &p[i].e);
sort(p + 1, p + 1 + n);
priority_queue<int, vector<int>, greater<int> > q;
for (int i = 1; i <= n; i++) {
if (q.empty()) {
//直接开一个
q.push(p[i].e);
} else {
int t = q.top();
if (p[i].s > t) {
q.pop();
}
q.push(p[i].e);
}
}
printf("%d\n", q.size());
return 0;
}
上课讲述代码:
#include
using namespace std;
template <class Type>
void GreedySelector(int b,int n,Type s[],Type f[],bool A[])
{
A[b]=true;
int j=b;
for(int i=b+1;i<=n;i++)
if(!A[i] && s[i]>=f[j])
{
A[i]=true;
j=i;
}
}
int main()
{
int n=5;
int s[n+1]={0, 1,12,25,36,27};
int f[n+1]={0,23,28,35,50,80};
bool A[n+1];
int j=0;
for(int i=1;i<=n;i++)
if(!A[i])
{
GreedySelector(i,n,s,f,A);
j++;
}
cout<<j;
return 0;
}
从开始结点出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。
如果在当前的扩展结点处不能再向纵深方向移动,则当前的扩展结点就成为死结点。换句话说,这个结点不再是一个活结点。此时,应往回移动至最近的一个活结点处,并使这个活结点成为当前的扩展结点。
有一批共n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为wi,且∑1_(i=1)^n▒w_i ≤c_1+c_2
装载问题要求确定是否有一个合理的装载方案可将这n个集装箱装上这2艘轮船。如果有,找出一种装载方案。
void backtrack(int i)
{//搜索第i层结点
if(i>n) {//到达叶结点
if(cw>bestw) bestw=cw;
return;
}
//搜索子树
r -=w[i];
if(cw+w[i]<=c)
{ //搜索左子树
x[i]=1;//可行,装载集装箱i
cw+=w[i];//更新当前装载量
backtrack(i+1);//搜索第i+1层结点
cw-=w[i];
}
if(cw+r>bestw) //进行剪枝 若不选这个而去
{ //搜索右子树
x[i]=0;
backtrack(i+1);
}
r+=w[i];
}
void backtrack(int i)
{//搜索第i层结点
if(i>n) {//到达叶结点
if(cw>bestw) bestw=cw;
return;
}
//搜索子树
r -=w[i];
if(cw+w[i]<=c)
{ //搜索左子树
x[i]=1;//可行,装载集装箱i
cw+=w[i];//更新当前装载量
backtrack(i+1);//搜索第i+1层结点
cw-=w[i];
}
if(cw+r>bestw) //进行剪枝 若不选这个而去
{ //搜索右子树
x[i]=0;
backtrack(i+1);
}
r+=w[i];
}
#include
const int N = 10005;
int a[N], n, m, rec[N];
bool ok;
void dfs(int start, int sum, int cnt) {
if (sum > m) return ;//剪枝
if (sum == m) {
for (int i = 0; i < cnt; i++) printf("%d ", rec[i]);
ok = true;
return ;
}
for (int i = start; i <= n; i++) {
rec[cnt] = a[i]; //记录当前选的值
dfs(i + 1, sum + a[i], cnt + 1); //对下一个进行搜索
if (ok) return;
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
dfs(1, 0, 0);
// if (!ok) printf("Solution!");
return 0;
}