POJ 2686(状压DP

第一次做状压感觉那一长串for显示了这是个多么暴力的算法呢。。。1A了倒是挺顺的

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#define INF 0x3fffffff
#define pb push_back
#define pn(x) cerr<<x<<endl

using namespace std;
typedef long long ll;
const int maxv=100005;

int n,m,p,a,b;
int t[10];
int G[35][35];
double dp[35][1<<9];////记录顶点和用掉的票的集合
int main(){
////freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(cin>>n>>m>>p>>a>>b){
        memset(G,0,sizeof G);
        if(!(n||m||p||a||b)) break;
        for(int i=0;i<n;i++) cin>>t[i];
        for(int i=0;i<p;i++){
            int v1,v2,w;
            scanf("%d%d%d",&v1,&v2,&w);
            G[v1][v2]=G[v2][v1]=w;
        }
        for(int i=0;i<35;i++)
            for(int j=0;j<1<<9;j++) dp[i][j]=1e10;
        dp[a][0]=0;
        for(int used=0;used<1<<n;used++)
            for(int i=1;i<=m;i++)
                for(int j=0;j<n;j++)
                    if(used&1<<j)
                        for(int k=1;k<=m;k++)
                            if(G[i][k])
                                dp[k][used]=min(dp[k][used],dp[i][used&~(1<<j)]+G[i][k]/(double)t[j]);
        double ans=1e11;
        for(int i=0;i<1<<n;i++) ans=min(ans,dp[b][i]);
        if(ans>1e9) cout<<"Impossible"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}
时间: 2024-10-17 22:30:07

POJ 2686(状压DP的相关文章

POJ 1038 状压DP

一个公司生产一种2*3规模的芯片,但是原材料上面有一些地方是不能用来当作芯片材料的,给出原料大小,及上面不能做原料的点,问你怎么分解,可以使生成芯片最大化. 对M进行三进制状压 last数组存储第i-1行和i-2行状态,cur数组存储i行和i-1行状态 cur[k]=2; // 本行k位置和上行k位置都不可用 cur[k]=1; // 本行k位置可用,上行k位置不可用 cur[k]=0; // 本行和上行位置k均可用 必须用滚动数组,否则爆内存 #include "stdio.h" #

POJ 3254 (状压DP) Corn Fields

基础的状压DP,因为是将状态压缩到一个整数中,所以会涉及到很多比较巧妙的位运算. 我们可以先把输入中每行的01压缩成一个整数. 判断一个状态是否有相邻1: 如果 x & (x << 1) 非0,说明有相邻的两个1 判断一个状态能否放在该行: 如果 (a[i] & state) != state,说明是不能放置的.因为a[i]中存在某个0和对应state中的1,与运算之后改变了state的值 判断相邻两行的状态是否有同一列相邻的1: 如果(state & _state)不

Best Sequence(poj 1699) 状压dp(TSP)

类似于前两天做的那个wordstack.状压的其实有时候爆搜+记忆化也差不多. 就是这个是要与之前的都重合,移位预处理要注意. 理解好第一个样例就行 /* *********************************************** Author :bingone Created Time :2014/12/9 22:48:56 File Name :a.cpp ************************************************ */ #inclu

POJ 3254 状压DP

题目大意: 一个农民有一片n行m列 的农场   n和m 范围[1,12]  对于每一块土地 ,1代表可以种地,0代表不能种. 因为农夫要种草喂牛,牛吃草不能挨着,所以农夫种菜的每一块都不能有公共边. 告诉你 n ,m 和那些地方能种菜哪些地方不能种菜,求农夫一共有多少种方案种菜 解法: 基本思想是状压 也就是用一个int 型的数代表一行的种菜策略,二进制的0代表该位不能种菜,1位代表能种菜,使用位运算使处理速度变快 对于单行行,最多有2^12 种情况,并且 2^12种情况里面还有很多不满足题意的

POJ 2411 状压DP经典

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 16771   Accepted: 9683 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

poj 3254 状压dp入门题

1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相邻,求有多少种放法. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #d

poj 2923 状压dp+01背包

好牛b的思路 题意:一系列物品,用二辆车运送,求运送完所需的最小次数,两辆车必须一起走 解法为状态压缩DP+背包,本题的解题思路是先枚举选择若干个时的状态,总状态量为1<<n,判断这些状态集合里的那些物品能否一次就运走,如果能运走,那就把这个状态看成一个物品.预处理完能从枚举中找到tot个物品,再用这tol个物品中没有交集(也就是两个状态不能同时含有一个物品)的物品进行01背包,每个物品的体积是state[i],价值是1,求包含n个物品的最少价值也就是dp[(1<<n)-1](dp

POJ 2411 状压dp

题目大意: 用 1*2 或者2 *1的木板填满 h*w的长方形,问总共有多少种填充方法 直接dfs会超时,因为后面答案甚至爆了int,直接搜,肯定也是long long 的时间复杂度 这里我们将当前位置没放置任何木板为 0 , 如有放置则看为 1 每次通过当前行 i 的状态 old 找到下一行 i + 1 所有满足当前行状态的状态 new , 将 dp[i+1][new] += dp[i][old] 这个new的状态一定会在old状态为 0 的位置为1 , 因为上一行为 0 , 说明是留给竖木板

POJ 1185 状压DP

legal[] 保存所有在当前行可显示的状态,由dfs得到,len[]保存legal[]对应下标状态中的 1 的个数 , 也就是放置炮台的个数 state[i] 表示第 i 行这块区域的土地情况,H表示 1 ,P表示 0 那么每次加入一个legal状态  都要符合 !(legal[i] & state[k]) 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namesp