dp之状态压缩水题总结

状态压缩dp

其实就是 将状态表示成二进制,然后用位运算进行求解

poj 3311

Hie with the Pie

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 5080   Accepted: 2706

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 processed before he starts any deliveries. Needless to say, he would like to take the shortest route in delivering these goodies and returning to the pizzeria, even if it means passing the same location(s) or the pizzeria more than once on the way. He has commissioned you to write a program to help him.

Input

Input will consist of multiple test cases. The first line will contain a single integer n indicating the number of orders to deliver, where 1 ≤ n ≤ 10. After this will be n + 1 lines each containing n + 1 integers indicating the times to travel between the pizzeria (numbered 0) and the n locations (numbers 1 to n). The jth value on the ith line indicates the time to go directly from location i to location j without visiting any other locations along the way. Note that there may be quicker ways to go from i to j via other locations, due to different speed limits, traffic lights, etc. Also, the time values may not be symmetric, i.e., the time to go directly from location i to j may not be the same as the time to go directly from location j to i. An input value of n = 0 will terminate input.

Output

For each test case, you should output a single number indicating the minimum time to deliver all of the pizzas and return to the pizzeria.

Sample Input

3
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
0

Sample Output

8

Source

East Central North America 2006

TSP问题

dp[状态]【i】 表示 经过i点时候的状态。1A!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define INF 0x7fffffff
#define maxn 10010
int n,dp[maxn][12],a[12][12],ans;
void floyd()
{
    for(int k=0;k<=n;k++)
    {
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
                a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
            break;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
                scanf("%d",&a[i][j]);
        }
        floyd();
        for(int s=0;s<(1<<n);s++)
        {
            for(int i=1;i<=n;i++)
            {
                if(s&(1<<(i-1)))
                {
                    if(s==(1<<(i-1))) dp[s][i]=a[0][i];
                    else
                    {
                        dp[s][i]=INF;
                        for(int j=1;j<=n;j++)
                        {
                            if(i!=j&&(s&(1<<(j-1))))
                                dp[s][i]=min(dp[s][i],dp[s^(1<<(i-1))][j]+a[j][i]);
                        }
                    }
                }
            }
        }
        ans=dp[(1<<n)-1][1]+a[1][0];
        for(int i=2;i<=n;i++)
            if(ans>dp[(1<<n)-1][i]+a[i][0])
                ans=dp[(1<<n)-1][i]+a[i][0];
        printf("%d\n",ans);
    }
    return 0;
}

  

时间: 2024-10-03 13:57:35

dp之状态压缩水题总结的相关文章

HDU 4352 XHXJ&amp;#39;s LIS(数位dp&amp;amp;状态压缩)

题目链接:[kuangbin带你飞]专题十五 数位DP B - XHXJ's LIS 题意 给定区间.求出有多少个数满足最长上升子序列(将数看作字符串)的长度为k. 思路 一个数的上升子序列最大长度为10,所以每个上升子序列的状态都能够用10个二进制位来表示. 上升子序列的变化能够用LIS的方式来更新. dp[len][num][k] len为当前的位,num为当前上升子序列的状态.k表示子序列的长度. next[s][num]为记录预处理的子序列的状态变化. cnt [num]记录各个状态的最

POJ-3254-Corn Fields-DP+状态压缩(入门题)

题目链接:http://poj.org/problem?id=3254 题目意思:给你一个n*m的牧场,叫你带牛去吃草,其中0代表没有草不可以放牧,1代表有草可以放牧.而且两头牛不可以相邻,叫你求所有可能的放牧方案. 思路:这是个状态压缩的基础题,刚学状态压缩的可以用这个题目来理解状态压缩:(如果是刚学DP我建议理解题意后先粗略的看一下代码后再边看代码边看我的思路,效果更佳) 1.题目告诉我们两头牛不能相邻,那么我们就可以枚举出每一行的所有情况,并且用数组st保存起来:怎么枚举每一种情况呢,题目

poj1185 状态压缩经典题

状态压缩的好题,直接求会爆内存,先把所有可能的状态求出来存在stk里,然后f[i][k][t]表示i行状态为t,i-1状态为k,由i-1状态来推出i状态即可 注意要打好边际条件的状态,并且某个可行状态必须由前一个可行状态推出 /* f[i][k][t]表示第i行状态为t,第i-1行状态为k的炮兵数 边际条件:第一行为任意可行状态即dp[1][1][i]=num[i] */ #include<bits/stdc++.h> using namespace std; #define ll long

状态压缩简单题

状态压缩·一 题目传送:#1044 : 状态压缩·一 AC代码: #include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cctype> #include <cstdi

SPOJ BALNUM Balanced Numbers(数位dp,状态压缩)

BALNUM - Balanced Numbers no tags 题目链接 Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a balanced number if: 1)      Every even digit appears an odd number of times in its decimal representation 2)   

hdu4064 三进制状态压缩 好题!

还不太会做这类题,总之感觉有点难啊. 用深搜代替打表求出一行所有的可行状态,注意要进行剪枝 这是自己理解的代码,但是tle了 #include<bits/stdc++.h> using namespace std; #define mod 1000000007 #define maxn 600005 int n,m,dp[2][maxn],sum; char mp[15][15][15]; int a[200],tag,flag,s[15]; // void dfs(int r,int num

[CF55D]Beautiful numbers(数位dp,状态压缩)

题目链接:http://codeforces.com/problemset/problem/55/D 题意:给定区间,求区间内某数的所有数位能整除这个数本身的数的个数. 起初思路:dp(l,s,sum)表示这个数到l位,并且0~9出现的状态s,和为sum的时候的数字个数.发现这个sum不好处理,因为数字越来越大无法保证这个界限.用到一个性质:一个数能被一堆数整除,当且仅当这个数能被这堆数的最小公倍数整除.换句话说,我们统计这个数对1~9的最小公倍数取模,就能判断这个sum是否可以被各位数整除了.

Traveling by Stagecoach 状态压缩裸题

Traveling by Stagecoach dp[s][v]  从源点到达  v,状态为s,v的最小值.  for循环枚举就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector>

1349. Maximum Students Taking Exam(DP,状态压缩)

题目 Maximum Students Taking Exam Add to List Share Given a m * n matrix seats that represent seats distributions in a classroom. If a seat is broken, it is denoted by '#' character otherwise it is denoted by a '.' character. Students can see the answe