POJ_S1E02_Recursion&DP(4)

OUTLINE:
滑雪

UNIMODAL PALINDROMIC DECOMPOSITIONS

Charm Bracelet//背包问题

小精灵收服//测评感人,居然一次就过了>-< O(∩_∩)O哈哈哈~
海贼王的伟大航路//状压DP&&不同于双调的另一种商旅问题

Basic idea:
the Sierpinski Fractal
1.DFS——左顶点、右顶点、上顶点分别记为0、 1、 2 点,0为父节点,1 、 2为子节点
2.每个节点都对应一个单元三角形
3.涉及二维制图,先画再输出
提交人班级结果内存时间代码长度语言提交时间
1400012972北京大学Accepted41176kB60ms1300 BG++刚刚
1400012972北京大学Accepted8968kB90ms738 BG++1小时前
上面那个是DP,三维数组里面存图形;下面那个是DFS,代码如下
贴代码

#include <stdio.h>
#include <string.h>
#include <math.h>


char map[3000][3000];
void dfs(int level, int fx, int fy){
if (level == 1){
map[fx][fy] = map[fx - 1][fy + 1] = '/';
map[fx][fy + 1] = map[fx][fy + 2] = '_';
map[fx - 1][fy + 2] = map[fx][fy + 3] = '\\';
return;
}
int size = pow(2.0, level - 1);
dfs(level - 1, fx, fy);
dfs(level - 1, fx - size, fy + size);
dfs(level - 1, fx, fy + 2 * size);
return;
}

int main()
{
int lev = 0;
while (scanf("%d", &lev), lev){
memset(map, ' ', sizeof(map));
int size = pow(2.0, lev);
dfs(lev, size, 1);
int i = 0, j = 0;
for (i = 1; i <= size; ++i){
for (j = 1; j <= 2 * size; ++j)
printf("%c", map[i][j]);
printf("\n");
}
printf("\n");
}

return 0;
}


滑雪
1.题目很经典,关键是速度
2.关键点和易错点是初始化——注意初始化的实际含义:0?1?-1?+INF?-INF?
贴代码

#include <stdio.h>
#include <stdlib.h>
#define max(a,b) (a>b?a:b)

const int MAX_SIZE=100;
struct point
{
int x, y;
int h;
};
int mycmp(const void*elem1, const void*elem2){
return((point*)elem2)->h - ((point*)elem1)->h;
}
int main()
{
int r = 0, c = 0;
int i = 0, j = 0;
int height[MAX_SIZE + 10][MAX_SIZE + 10] = { 0 };
int mark[MAX_SIZE + 10][MAX_SIZE + 10] = { 0 };
point points[MAX_SIZE*MAX_SIZE + 10];
const int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };

scanf("%d%d", &r, &c);
int n = 0;
for (i = 1; i <= r;++i)
for (j = 1; j <= c; ++j){
scanf("%d", &height[i][j]);
points[n++].h = height[i][j];
points[n - 1].x = i; points[n - 1].y = j;
}
qsort(points, n, sizeof(point), mycmp);

int result = 1;
mark[points[0].x][points[0].y] = 1;
for (i = 1; i < n; ++i){
mark[points[i].x][points[i].y] = 1;
for (j = 0; j < 4; ++j){
if (height[points[i].x + dir[j][0]][points[i].y + dir[j][1]]>height[points[i].x][points[i].y]){
mark[points[i].x][points[i].y] = max(mark[points[i].x][points[i].y], mark[points[i].x + dir[j][0]][points[i].y + dir[j][1]] + 1);
result = max(result, mark[points[i].x][points[i].y]);
}
}
}
printf("%d\n", result);

return 0;
}


单调回文数
1.类似放苹果和最长单调子列
2.注意爆int啊~~>-<

for (i = 1; i <= max_n; ++i){
dp[i][i] = 1; dp[0][i] = 1;
}
for (i = 2; i <= max_n;++i)
for (j = i - 1; j > 0; --j){
if (i >= 2 * j)
dp[i][j] = dp[i - 2 * j][j] + dp[i][j + 1];
else
dp[i][j] = dp[i][j + 1];
}

背包问题:
POJ_S1E02_RecursionDP(4) - 五月 - 我要阳光
优化1——对确定的V,只有V-vi会影响
2——完全背包问题中可以去掉性价比低的物品
3——多重背包问题
POJ_S1E02_RecursionDP(4) - 五月 - 我要阳光
4——拓展:二维费用背包问题、分组背包问题
贴代码

int main()

 {

     int num[xxx],a[xxx];

     scanf("%d",&n);

     for(i=0;i<n;i++)

         scanf("%d",&a[i]);

     memset(num,0,sizeof(num));


     for(i=0;i < n;i++) {

        int k = 40 - a[i];

         while(k >= 0){

             if(num[k] > 0)

                num[k+a[i]] = num[k+a[i]] + num[k];

            k--;

        }

         num[a[i]]++;

     }//@@@@@用二维处理时注意数据的继承@@@@@

     printf("%d\n",num[40]);

 }


  二维代码://感人的一次过代码

#include <stdio.h>

struct mypair
{
int c;
int used_v2;
mypair(int a = 0, int b = 0):c(a), used_v2(b){}
};

inline mypair mymax(const mypair elem1, const mypair elem2){
if (elem1.c > elem2.c) return elem1;
if (elem1.c == elem2.c&&elem1.used_v2 < elem2.used_v2) return elem1;
return elem2;
}
const int max_v1 = 1000, max_v2 = 500;
const int max_n = 100;
const int INF = 10000000;
mypair dp[max_v1 + 10][max_v2 + 10];
int n[max_n + 10][2] = { 0 };

int main()
{
int N = 0, M = 0, K = 0;//N:v1;M:v2;k:n
int C = 0, R = 0;
int i = 0, j = 0;

scanf("%d%d%d", &N, &M, &K);
for (i = 1; i <= K; ++i)
scanf("%d%d", &n[i][0], &n[i][1]);

for (int nn = 1 ; nn <= K; ++nn){
for (i = N; i >= 1; --i){
for (j = M; j >= 1; --j){
if (i - n[nn][0] >= 0 && j - n[nn][1] >= 0){
mypair tmp = dp[i - n[nn][0]][j - n[nn][1]];
tmp.c++; tmp.used_v2 += n[nn][1];
dp[i][j] = mymax(dp[i][j], tmp);
}
}
}

}
printf("%d %d\n", dp[N][M].c, M - dp[N][M].used_v2);

return 0;
}

伟大航路:
1. dp[state][i]:state为经过除起始点外点的集合,i为路线终点
2. dp[s][i]=min{dp[s][i],dp[s'][j]+dist[j][i]}//j属于s
3. 可重复经过点的时候,只需在初始化时,优化dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j])

#include <stdio.h>
#define mmin(a,b)(a<b?a:b)

int dp[1 << 20][20] = { 0 };
int main()
{
int n = 0; int i = 0, j = 0;
int dist[20][20] = { 0 };
const int INF = 1000000;

scanf("%d", &n);
for (i = 1; i <= n; ++i)
for (j = 1; j <= n; ++j)
scanf("%d", &dist[i][j]);

//重复可走的优化做在这里


for (int s = 1; s < (1 << (n-1)); ++s){
for (i = 2; i <= n; ++i){
if (s == (1 << (i - 2))) dp[s][i] = dist[1][i];
else if (s & (1 << (i - 2))){
dp[s][i] = INF;
for (j = 2; j <= n; ++j){
if (s & (1 << (j - 2)) && j != i)
dp[s][i] = mmin(dp[s][i], dp[s ^ (1<<(i - 2))][j] + dist[j][i]);
}
}
}//i
}//s

printf("%d\n", dp[(1 << (n - 1))-1][n]);

return 0;

}


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值