dp周训练 状态压缩

题目链接:题意:给你一个10*10的矩阵,每到一个格子中都要拿一个0-9的数值,求从矩阵左上方走到右下方且必须0-9都经过,拿的数值和最小是多少;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1);
const int mod=100000000;
ll max(ll a,ll b)
{return a>b?a:b;};
int min(int a,int b)
{return a<b?a:b;};

int a[12][12],dp[12][12][(1<<12)];
int main()
{
    MM(dp,inf);
    for(int i=1;i<=10;i++)
        for(int j=1;j<=10;j++)
            {
                int v;
                scanf("%d",&v);
                if(i==1&&j==1) dp[i][j][1<<v]=v;
                a[i][j]=v;
            }

    for(int i=1;i<=10;i++)
       for(int j=1;j<=10;j++)
         for(int k=0;k<=(1<<10)-1;k++)
         {
             int v=a[i+1][j];
             dp[i+1][j][k|(1<<v)]=min(dp[i+1][j][k|(1<<v)],dp[i][j][k]+v);
             v=a[i][j+1];
             dp[i][j+1][k|(1<<v)]=min(dp[i][j+1][k|(1<<v)],dp[i][j][k]+v);
         }
    printf("%d\n",dp[10][10][(1<<10)-1]);
    return 0;
}

  本来一血的,犯了个傻逼错误;看wa代码;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1);
const int mod=100000000;
ll max(ll a,ll b)
{return a>b?a:b;};
int min(int a,int b)
{return a<b?a:b;};

int a[12][12],dp[12][12][(1<<12)];
int main()
{
    MM(dp,inf);
    for(int i=1;i<=10;i++)
        for(int j=1;j<=10;j++)
            {
                int v;
                scanf("%d",&v);
                dp[i][j][1<<v]=v;
                a[i][j]=v;
            }

    for(int i=1;i<=10;i++)
       for(int j=1;j<=10;j++)
         for(int k=0;k<=(1<<10)-1;k++)
         {
             int v=a[i+1][j];
             dp[i+1][j][k|(1<<v)]=min(dp[i+1][j][k|(1<<v)],dp[i][j][k]+v);
             v=a[i][j+1];
             dp[i][j+1][k|(1<<v)]=min(dp[i][j+1][k|(1<<v)],dp[i][j][k]+v);
         }
    printf("%d\n",dp[10][10][(1<<10)-1]);
    return 0;
}

  犯错原因:初始化时对每个格子都dp[i][j][1<<v]=v;没道理啊,,题目都说了必须从左上角开始走

时间: 2024-10-15 06:05:21

dp周训练 状态压缩的相关文章

状态压缩DP

I - 方格取数(1) Crawling in process... Crawling failed Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description Input Output Sample Input Sample Output Hint Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.   从中取出若干个数,

学习笔记:状态压缩DP

我们知道,用DP解决一个问题的时候很重要的一环就是状态的表示,一般来说,一个数组即可保存状态.但是有这样的一些题 目,它们具有DP问题的特性,但是状态中所包含的信息过多,如果要用数组来保存状态的话需要四维以上的数组.于是,我们就需要通过状态压缩来保存状态,而 使用状态压缩来保存状态的DP就叫做状态压缩DP. 一道例题: HOJ 2662 有一个n*m的棋盘(n.m≤80,n*m≤80)要在棋盘上放k(k≤20)个棋子,使得任意两个棋子不相邻(每个棋子最多和周围4个棋子相邻).求合法的方案总数.

Light OJ 1316 A Wedding Party 最短路+状态压缩DP

题目来源:Light OJ 1316 1316 - A Wedding Party 题意:和HDU 4284 差不多 有一些商店 从起点到终点在走过尽量多商店的情况下求最短路 思路:首先预处理每两点之前的最短路 然后只考虑那些商店 个数小于15嘛 就是TSP问题 状态压缩DP搞一下 状态压缩姿势不对 有必要加强 #include <cstdio> #include <algorithm> #include <queue> #include <vector>

算法练习系列—hiho1048 状态压缩一(铺地砖)

题目地址:http://hihocoder.com/problemset/problem/1048 编程之美的课后题也有一个和整个题目一样的.(P269) 题目 这个题目的题意很容易理解,在一个N*M的格子里,我们现在有两种类型的砖块,1 * 2和 2 * 1,问一共有多少种方案,可以将整个N*M的空间都填满. 最简单的例子就是下面的了: 编程之美中题目: 某年夏天,位于希格玛大厦四层的微软亚洲研究院对办公楼的天井进行了一次大规模的装修.原来的地板铺有 N×M 块正方形瓷砖,这些瓷砖都已经破损老

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

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

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

HDU3001(KB2-J 状态压缩dp)

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8103    Accepted Submission(s): 2642 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

2017盛大游戏杯 零件组装(状态压缩DP之巧妙枚举子集)

题目链接:2017盛大游戏杯 零件组装 题意: 有n个零件,给你相邻关系和排斥关系,每两块零件组装起来有一个代价,问最少的代价总和是多少. 题解: 考虑状态压缩,dp[i]表示i这个集合为一个零件块. 那么要枚举一下i的子集.O(3^n). 先要预处理一下每个集合的排斥个数和相邻个数,然后容斥一下就可以了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int

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个格子不能相邻,并且取出的数