HDU2167(SummerTrainingDay02-D 状态压缩dp)

Pebbles

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1820    Accepted Submission(s): 1034

Problem Description

You‘re given an unlimited number of pebbles to distribute across an N x N game board (N drawn from [3, 15]), where each square on the board contains some positive point value between 10 and 99, inclusive. A 6 x 6 board might look like this:

The player distributes pebbles across the board so that:

?At most one pebble resides in any given square.
?No two pebbles are placed on adjacent squares. Two squares are considered adjacent if they are horizontal, vertical, or even diagonal neighbors. There‘s no board wrap, so 44 and 61 of row three aren‘t neighbors. Neither are 33 and 75 nor 55 and 92.

The goal is to maximize the number of points claimed by your placement of pebbles.

Write a program that reads in a sequence of boards from an input file and prints to stdout the maximum number of points attainable by an optimal pebble placement for each.

Input

Each board is expressed as a series of lines, where each line is a space-delimited series of numbers. A blank line marks the end of each board (including the last one)

Output

then your program would print the maximum number of points one can get by optimally distributing pebbles while respecting the two rules, which would be this (each output should be printed on a single line and followed with a newline):

Sample Input

71 24 95 56 54
85 50 74 94 28
92 96 23 71 10
23 61 31 30 46
64 33 32 95 89

78 78 11 55 20 11
98 54 81 43 39 97
12 15 79 99 58 10
13 79 83 65 34 17
85 59 61 12 58 97
40 63 97 85 66 90

33 49 78 79 30 16 34 88 54 39 26
80 21 32 71 89 63 39 52 90 14 89
49 66 33 19 45 61 31 29 84 98 58
36 53 35 33 88 90 19 23 76 23 76
77 27 25 42 70 36 35 91 17 79 43
33 85 33 59 47 46 63 75 98 96 55
75 88 10 57 85 71 34 10 59 84 45
29 34 43 46 75 28 47 63 48 16 19
62 57 91 85 89 70 80 30 19 38 14
61 35 36 20 38 18 89 64 63 88 83
45 46 89 53 83 59 48 45 87 98 21

15 95 24 35 79 35 55 66 91 95 86 87
94 15 84 42 88 83 64 50 22 99 13 32
85 12 43 39 41 23 35 97 54 98 18 85
84 61 77 96 49 38 75 95 16 71 22 14
18 72 97 94 43 18 59 78 33 80 68 59
26 94 78 87 78 92 59 83 26 88 91 91
34 84 53 98 83 49 60 11 55 17 51 75
29 80 14 79 15 18 94 39 69 24 93 41
66 64 88 82 21 56 16 41 57 74 51 79
49 15 59 21 37 27 78 41 38 82 19 62
54 91 47 29 38 67 52 92 81 99 11 27
31 62 32 97 42 93 43 79 88 44 54 48

Sample Output

572
683
2096
2755

Source

2007 ACM-ICPC Pacific Northwest Region

 1 //2017-08-02
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5
 6 using namespace std;
 7
 8 int arr[22][22];
 9 int dp[22][20000], sum[22][20000];//dp[i][j]表示第i行使用第j种方法所能得到的最大值,sum[i][j]表示第i行使用第j种方法所得的和
10 int state[20000];//表示可行的状态,即可行的取数方法
11 int len, n;
12
13 bool ok(int sta)//可行状态,即1的位置两两不相邻
14 {
15     return (sta&(sta<<1))==0 ? true : false;
16 }
17
18 int get_sum(int pos, int x)//求第pos行,使用x方法能取得的和
19 {
20     int sum = 0, cnt = 1;
21     while(x)
22     {
23         sum += (x%2)*arr[pos][n-cnt];
24         x >>= 1;
25         cnt++;
26     }
27     return sum;
28 }
29
30 void init(int m)//初始化
31 {
32     len = 0;
33     for(int i = 0; i < (1<<m); i++)
34           if(ok(i))state[len++] = i;
35     for(int i = 0; i < n; i++)
36         for(int j = 0; j < len; j++)
37             sum[i][j] = get_sum(i, state[j]);
38     memset(dp, 0, sizeof(dp));
39     for(int i = 0; i < len; i++)
40           dp[0][i] = sum[0][i];
41 }
42
43 void read(){
44     char str[200];
45     int row = 0;
46     while(cin.getline(str, 200)){
47         if(strlen(str) == 0)break;
48         for(int i = 0; i < strlen(str); i+=3){
49             arr[row][i/3] = (str[i]-‘0‘)*10+(str[i+1]-‘0‘);
50         }
51         row++;
52     }
53     n = row;
54 }
55
56 int main()
57 {
58     while(1)
59     {
60         read();
61         if(n == 0)break;
62         init(n);
63         for(int i = 1; i < n; i++)//处理第i行
64             for(int j = 0; j < len; j++)//采取第j种方法
65                 for(int k = 0; k < len; k++)//枚举上一行所采取的方法k
66                     if((state[j]&state[k])==0 && ((state[j]<<1)&state[k])==0 && ((state[j]>>1)&state[k])==0)//方法j、k可行。
67                         dp[i][j] = max(dp[i][j], dp[i-1][k]+sum[i][j]);//状态转移方程
68
69         int ans = 0;
70         for(int i = 0; i < len; i++)//找出最大值
71             if(dp[n-1][i]>ans)
72                   ans = dp[n-1][i];
73
74         cout<<ans<<endl;
75     }
76     return 0;
77 }
时间: 2024-12-12 16:55:57

HDU2167(SummerTrainingDay02-D 状态压缩dp)的相关文章

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

HDU1565(状态压缩dp)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8170    Accepted Submission(s): 3095 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数

HDU 3001【状态压缩DP】

题意: 给n个点m条无向边. 要求每个点最多走两次,要访问所有的点给出要求路线中边的权值总和最小. 思路: 三进制状态压缩DP,0代表走了0次,1,2类推. 第一次弄三进制状态压缩DP,感觉重点是对数据的预处理,利用数组分解各个位数,从而达到类似二进制的目的. 然后就是状态的表示,dp[s][i]表示状态s时到达i的最优值. 状态转移也一目了然,不废话. #include<stdio.h> #include<string.h> #include<algorithm> u

Victor and World(spfa+状态压缩dp)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)Total Submission(s): 958    Accepted Submission(s): 431 Problem Description After trying hard fo

poj 3311 Hie with the Pie(状态压缩dp)

Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can afford to hire only one driver to do the deliveries. He will wait for 1 or more (up to 10) orders to be

HDU--1074(状态压缩DP)

典型的状态压缩DP,给出了每件作业的截止时间和花费,求让老师扣分最少的写作业方式.把完成n种作业用状态2^n-1表示,dp[s]表示 完成状态s时,最小扣分.比如“111”,那么可以由“011”,“110”,“101”转移过来,分别表示选了0,1号作业,1,2号作业,0,2号作业. t[s]表示状态S记录的总时间.dp[s] = min{dp[j]+c[k] - d[k]},其中j = i^(1<<k),0<k<n;pre[s]表示状态s完成时,最末尾完成的作业, #include

poj 3254 Corn Fields(状态压缩dp)

Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and

poj 2411 Mondriaan&#39;s Dream(状态压缩+dp)

 题意:用1*2砖块铺满n*m的房间. 思路转自:http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html 因为这道题输入范围在11*11之间,所以可以先打表直接输出.......... 状态压缩DP 经典覆盖问题,输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案 其中n和m均为奇数的话,矩形面积就是奇数,可知是不可能完全覆盖的.接着我们来看

1252 - Twenty Questions(状态压缩DP)

经典的状态压缩DP .  有没有感觉这道题和什么东西有点像?  没错,是01背包 . 将特征看作物品 , 只不过这里的状态有点复杂, 需要用一个集合才能表示它, 所以我们用d[s][a]来表示,已经询问了特征集s , 假设我们要猜的物品是w ,w所具备的特征集为a ,此时还要询问的最小次数 .   显然a是s的子集,而且要注意本题的要求, 求的是最小化的最大询问次数 .也就是说无论猜哪个物品,猜这么多次一定能猜到 . 那么状态如何转移呢? 就像背包问题,对于一个特征k ,我们要抉择:要k还是不要

hoj 2662 状态压缩dp

题意: 给定mxn的棋盘,要往其中放d枚棋子,其中,一枚棋子的上下左右四个位置不能再放棋子.求所有合法的放置状态 ( 0<m,n<=80 , mxn<=80 ) 棋盘位置可多达80,爆搜目测超时,我用的状态压缩dp. 棋盘中的一个格子,放棋用1,不放用0 压缩其中一维,每个状态数用一个二进制数表示. 每个状态都是棋盘一行的放置方法 假设,m >= n , 这个递推棋盘就有 m行 ,每行至多有 2^n-1个状态数.其实,没有这么多!按照题意,每个1的上下左右不能有1.对于一行,只知左