zoukankan      html  css  js  c++  java
  • dp练习 2016.2.24


      很经典的一道状压dp(似乎叫做旅行商问题),用f[i][s]表示在到达点i,已经经过的城市用二进制表示为s,于是方程就很简单了:

    f[i][s] = min { f[j][s ^ (1 << j)] + dis[j][i]| s & (1 << j) != 0}

      然后用记忆化搜索即可,注意方向,因为dis[i][j]可能不等于dis[j][i]。(下面的代码某个处理似乎没有必要)

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<fstream>
     7 #include<sstream>
     8 #include<algorithm>
     9 #include<map>
    10 #include<set>
    11 #include<queue>
    12 #include<vector>
    13 #include<stack>
    14 using namespace std;
    15 typedef bool boolean;
    16 #define INF 0xfffffff
    17 #define smin(a, b) a = min(a, b)
    18 #define smax(a, b) a = max(a, b)
    19 template<typename T>
    20 inline void readInteger(T& u){
    21     char x;
    22     int aFlag = 1;
    23     while(!isdigit((x = getchar())) && x != '-');
    24     if(x == '-'){
    25         x = getchar();
    26         aFlag = -1;
    27     }
    28     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
    29     ungetc(x, stdin);
    30     u *= aFlag;
    31 }
    32 
    33 int n;
    34 int dis[16][16];
    35 int f[16][(1 << 17)];
    36 boolean vis[16][(1 << 17)];
    37 
    38 inline void init() {
    39     readInteger(n);
    40     for(int i = 1; i <= n; i++)
    41         for(int j = 1; j <= n; j++)
    42             readInteger(dis[i][j]);
    43     for(int i = 1; i <= n; i++)
    44         dis[i][0] = dis[i][1], dis[0][i] = dis[1][i];
    45 }
    46 
    47 int dfs(int local, int status) {
    48     if(vis[local][status])    return f[local][status];
    49     vis[local][status] = true;
    50     for(int i = 0; i <= n; i++) {
    51         if(status & (1 << i)) {
    52             int ret = dfs(i, status ^ (1 << i));
    53             smin(f[local][status], f[i][status ^ (1 << i)] + dis[i][local]);
    54         }
    55     }
    56     return f[local][status];
    57 }
    58 
    59 inline void solve() {
    60     memset(vis, false, sizeof(vis));
    61     memset(f, 0x7f, sizeof(f));
    62     vis[1][0] = true;
    63     f[1][0] = 0;
    64     int res = dfs(0, (1 << (n + 1)) - 2);
    65     printf("%d", res);
    66 }
    67 
    68 int main() {
    69     freopen("salesman.in", "r", stdin);
    70     freopen("salesman.out", "w", stdout);
    71     init();
    72     solve();
    73     return 0;
    74 }



      因为关灯不耗时间,所以从一个地方走到另一个地方,从贪心的角度来讲,肯定要把沿路的灯都关掉,因此得到原问题转化成了区间dp。当然还要考虑是从做走到右还是从右走到左,当然可以直接用f[i][j]表示,但是为了防止各种手抽手贱导致半天调不出来,还是加了一维[0/1],表示在从右走到左(0)还是从左走到右。于是方程很容易就出来了,详细的看代码,这里就简单地写了,从f[i][j]转移到f[i - 1][j]或者f[i][j + 1],然后加上路程乘以未被关掉的所有灯的功率。

      至于这个功率可以用前缀和先预处理出,接着用总功率减去这一段的功率就行了。

      由于开始以为灯的位置不是有序的,特意排了道序,可以无视。

    Code

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<fstream>
      7 #include<sstream>
      8 #include<algorithm>
      9 #include<map>
     10 #include<set>
     11 #include<queue>
     12 #include<vector>
     13 #include<stack>
     14 using namespace std;
     15 typedef bool boolean;
     16 #ifdef    WIN32
     17 #define AUTO "%I64d"
     18 #else
     19 #define AUTO "%lld"
     20 #endif
     21 #define INF 0xfffffff
     22 #define smin(a, b) a = min(a, b)
     23 #define smax(a, b) a = max(a, b)
     24 template<typename T>
     25 inline void readInteger(T& u){
     26     char x;
     27     int aFlag = 1;
     28     while(!isdigit((x = getchar())) && x != '-');
     29     if(x == '-'){
     30         x = getchar();
     31         aFlag = -1;
     32     }
     33     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
     34     ungetc(x, stdin);
     35     u *= aFlag;
     36 }
     37 
     38 typedef class tower {
     39     public:
     40         int pos;
     41         int w;
     42         int index;
     43         tower(const int pos = 0, const int w = 0, const int index = 0):pos(pos), w(w), index(index) {        }
     44 
     45         boolean operator < (tower a) const {
     46             return pos < a.pos;
     47         }
     48 }tower;
     49 
     50 int n, c, rc;
     51 long long f[2][1005][1005];
     52 tower tows[1005];
     53 long long sumw[1005];
     54 
     55 inline void init() {
     56     readInteger(n);
     57     readInteger(c);
     58     for(int i = 1; i <= n; i++) {
     59         readInteger(tows[i].pos);
     60         readInteger(tows[i].w);
     61         tows[i].index = i;
     62     }
     63     sort(tows + 1, tows + n + 1);
     64     sumw[0] = 0;
     65     for(int i = 1; i <= n; i++) {
     66         sumw[i] = sumw[i - 1] + tows[i].w;
     67         if(tows[i].index == c)    rc = i;
     68     }
     69 }
     70 
     71 inline void solve() {
     72     memset(f, 0x37, sizeof(f));
     73     f[0][rc][rc] = f[1][rc][rc] = 0;
     74     if(rc > 1)
     75         f[0][rc - 1][rc] = (tows[rc].pos - tows[rc - 1].pos) * (sumw[n] - tows[rc].w);
     76     if(rc < n)
     77         f[1][rc][rc + 1] = (tows[rc + 1].pos - tows[rc].pos) * (sumw[n] - tows[rc].w);
     78     for(int l = 1; l < n; l++) {
     79         for(int i = 1; i + l <= n; i++) {
     80             int j = i + l;
     81             if(i > 1) {
     82                 smin(f[0][i - 1][j], f[0][i][j] + (sumw[n] - (sumw[j] - sumw[i - 1])) * (tows[i].pos - tows[i - 1].pos));
     83                 smin(f[0][i - 1][j], f[1][i][j] + (sumw[n] - (sumw[j] - sumw[i - 1])) * (tows[j].pos - tows[i - 1].pos));
     84             }
     85             if(j < n) {
     86                 smin(f[1][i][j + 1], f[1][i][j] + (sumw[n] - (sumw[j] - sumw[i - 1])) * (tows[j + 1].pos - tows[j].pos));
     87                 smin(f[1][i][j + 1], f[0][i][j] + (sumw[n] - (sumw[j] - sumw[i - 1])) * (tows[j + 1].pos - tows[i].pos));
     88             }
     89         }
     90     }
     91     long long res = smin(f[0][1][n], f[1][1][n]);
     92     printf(AUTO, res);
     93 }
     94 
     95 int main() {
     96     freopen("power.in", "r", stdin);
     97     freopen("power.out", "w", stdout);
     98     init();
     99     solve();
    100     return 0;
    101 }

    (题外话)

  • 相关阅读:
    Sitecore安全:访问权限
    Sitecore 8.2 防火墙规则的权威指南
    Sitecore 8.2 安全性第2部分:安全性编辑器和Access Viewer
    Sitecore安全性第1部分:自定义角色和权限
    Sitecore 8.2 Admin用户帐户解锁
    Sitecore 8.2 数据库权限设置
    cesium 结合 geoserver 实现地图属性查询(附源码下载)
    Vue&Cesium&Ribbon界面: 将桌面GIS搬进浏览器
    leaflet图斑历史时空播放(附源码下载)
    openlayers6结合geoserver实现地图属性查询(附源码下载)
  • 原文地址:https://www.cnblogs.com/yyf0309/p/6441976.html
Copyright © 2011-2022 走看看