现在以上面的第二种情况每种种类个数无限为例,给出模板:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
#include <iostream>
using namespace std;
// Author: Tanky Woo
// www.wutianqi.com
const int _max = 10001;
// c1是保存各项质量砝码可以组合的数目
// c2是中间量,保存没一次的情况
int c1[_max], c2[_max];
int main()
{ //int n,i,j,k;
int nNum; //
int i, j, k;
while(cin >> nNum)
{
for(i=0; i<=nNum; ++i) // ---- ①
{
c1[i] = 1;
c2[i] = 0;
}
for(i=2; i<=nNum; ++i) // ----- ②
{
for(j=0; j<=nNum; ++j) // ----- ③
for(k=0; k+j<=nNum; k+=i) // ---- ④
{
c2[j+k] += c1[j];
}
for(j=0; j<=nNum; ++j) // ---- ⑤
{
c1[j] = c2[j];
c2[j] = 0;
}
}
cout << c1[n] << endl;
}
return 0;
}
|
我们来解释下上面标志的各个地方:
① 、首先对c1初始化,由第一个表达式(1+x+x2+..xn)初始化,把质量从0到n的所有砝码都初始化为1.
② 、 i从2到n遍历,这里i就是指第i个表达式,上面给出的第二种母函数关系式里,每一个括号括起来的就是一个表达式。
③、j 从0到n遍历,这里j就是只一个表达式里第j个变量,比如在第二个表达式里:(1+x2+x4….)里,第j个就是x2*j.
③ k表示的是第j个指数,所以k每次增i(因为第i个表达式的增量是i)。
④ 、把c2的值赋给c1,而把c2初始化为0,因为c2每次是从一个表达式中开始的
#include <iostream>
using namespace std;
int num1[11111];
int num2[11111];
int main ()
{
int N;
while ( cin >> N , N )
{
for ( int i = 0 ; i <= N; ++ i )
{
num1[i] = 1;
num2[i] = 0;
}
for ( int i = 2; i <= 17; ++ i ) 从第二个表达时开始一直到第n个表达式
{
for ( int j = 0;j <= N; ++ j ) 从这个表达式其中的第j项(0---n)分别和所有可能的面值进行指数相加运算 ,j <= 最大可能的面值
{
for ( int k = 0; k + j <= N; k += i * i )
{
num2[j + k] += num1[j];
}
}
for ( int j = 0; j <= N; ++ j )
{
num1[j] = num2[j];
num2[j] = 0;
}
}
cout << num1[N] << endl;
}
return 0;
}
posted @
2010-08-21 11:24 雪黛依梦 阅读(306) |
评论 (0) |
编辑 收藏
//典型的搜索题,这里采用深度优先搜索
//1.本题如果不注意剪枝很容易超时,这里有两处剪枝
//2.深度搜索时主要是处理:1.具体题目中如何定深度,本题以某一个合法位置的四个方向是同一深度所以for 循环中steps + 1
// 2.理解回溯的思想
//HDU 1010
#include <stdio.h>
#include <stdlib.h>
int dir[4][2] = {{0, 1}, {-1, 0}, {0, -1},{1, 0}};
char block[9][9]; //迷宫数组
int si, sj; //入口
int di, dj; //出口
int m, n, t;
int steps;
bool escape;
int DFS (int curx, int cury, int steps)
{
//printf ("%d %d", curx, cury);
if (curx < 0 || curx == 0 || cury < 0 || cury == 0 || curx > m || cury > n) //该路径位置不合理,此次递归结束,但并不是整个递归结束
return 0;
if (curx == di && cury == dj && steps == t)
escape = 1;
//奇偶性剪枝
int temp = 0;
temp = (t - steps ) - abs (di - curx) - abs (dj - cury); //处在该位置的深搜是否有可能到达终点
if (temp < 0 || temp & 1) //当temp为奇数时 按位与是 1 ,temp为偶数时 按位是 0
return 0;
if (escape)
return 1;
for (int i = 0; i < 4; i ++)
{
if (block[curx + dir[i][0]][cury + dir[i][1]] != 'X') //因为也可以是D
{
block[curx + dir[i][0]][cury + dir[i][1]] = 'X';
DFS (curx + dir[i][0], cury + dir[i][1], steps + 1);
block[curx + dir[i][0]][cury + dir[i][1]] = '.';
}
}
}
int main ()
{
while ( scanf ("%d%d%d", &m, &n, &t) && (m != 0 && n != 0 && t != 0))
{
getchar ();
int wall = 0;
for (int i = 1; i <= m; i ++)
{
for (int j = 1; j <= n; j ++)
{
scanf ("%c", &block[i][j]);
if (block[i][j] == 'S') //入口坐标
{
si = i;
sj = j;
}
if (block[i][j] == 'D') //出口坐标
{
di = i;
dj = j;
}
if (block[i][j] == 'X')
{
wall ++;
}
}
getchar (); //错点
}
//printf ("%d %d", si, sj);
/**//*for (int i = 1; i <= m; i ++)
{
for (int j = 1; j <= n; j ++)
{
printf ("%d", block[i][j]);
}
}*/
if ( m * n - wall < t) //剪枝
{
printf ("NO\n");
continue;
}
escape = 0;
steps = 0;
block[si][sj] = 'X';
DFS (si, sj, steps);
if (escape)
printf ("YES\n");
else
printf ("NO\n");
}
system ("pause");
return 0;
}
posted @
2010-08-19 11:20 雪黛依梦 阅读(485) |
评论 (0) |
编辑 收藏