• [NOIP2016]愤怒的小鸟 DP


    ~~~题面~~~

    题解:

      首先观察数据范围,n <= 18,很明显是状压DP。所以设f[i]表示状态为i时的最小代价。然后考虑转移。

      注意到出发点(0, 0)已经被固定,因此只需要2点就可以确定一条抛物线,所以每次转移时枚举是哪两只猪确定了这条抛物线,然后由于一条抛物线可能会恰好打中别的猪,所以再枚举判断一下哪些猪会被打中,然后就获得了一个后续状态,直接转移即可。

      但是这样是$2^nn^3T$的复杂度,显然过不去,因此考虑优化。

      1,因为一旦确定抛物线的2只猪确定了,这条抛物线会经过哪些其他的猪也就确定了,所以我们可以预处理出g[i][j],表示用第i和第j只猪确定抛物线时总共可以打到哪些猪。

      2,因为观察到对于2条抛物线,先发射哪条不影响答案,同理,因为所有猪都必须被打,所以那只猪先被打掉也不影响答案,所以每次转移时只打状态中第一个没被打的猪,然后就可以break进入下一个状态了。因为这次没打的猪,下次还是会打掉的,因此不影响正确性。

      于是复杂度$2^nnT$

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define eps 1e-9
      5 #define AC 20
      6 #define ac 300000
      7 #define ld long double
      8 
      9 int T, n, m, maxn;
     10 int f[ac], g[AC][AC];
     11 struct node{
     12     ld x, y;
     13 }pig[AC], func;
     14 
     15 inline int read()
     16 {
     17     int x = 0;char c = getchar();
     18     while(c > '9' || c < '0') c = getchar();
     19     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     20     return x;
     21 }
     22 
     23 node cal(node x, node y)//计算解析式
     24 {
     25     ld a, b;
     26     a = (x.y * y.x - y.y * x.x) / (x.x * x.x * y.x - y.x * y.x * x.x);
     27     b = x.y / x.x - a * x.x;
     28     return (node){a, b};
     29 }
     30 
     31 inline void upmin(int &a, int b)
     32 {
     33     if(b < a) a = b;
     34 }
     35 
     36 bool check(node ff, node x)//计算一个点是否过解析式
     37 {
     38     ld a = ff.x, b = ff.y;
     39     return (fabs(x.y - (a * x.x * x.x + b * x.x)) <= eps);
     40 }
     41 
     42 void pre()
     43 {
     44     int x = 1, tmp;
     45     n = read(), m = read();
     46     maxn = (1 << n) - 1;
     47     memset(g, 0, sizeof(g));
     48     memset(f, 127, sizeof(f));
     49     f[0] = 0;
     50     for(R i = 1; i <= n; i ++) 
     51         scanf("%Lf%Lf", &pig[i].x, &pig[i].y);
     52     for(R i = 1; i <= n; i ++, x <<= 1)
     53     {
     54         int now = 1;
     55         for(R j = 1; j <= n; j ++, now <<= 1)
     56         {
     57             if(i == j) {g[i][j] = x; continue;}
     58             tmp = x | now; func = cal(pig[i], pig[j]);
     59             if(func.x >= 0) {g[i][j] = 0; continue;}//不合法
     60             int t = 1;
     61             for(R k = 1; k <= n; k ++, t <<= 1)
     62             {
     63                 if(k == i || k == j) continue;
     64                 if(!check(func, pig[k])) continue;
     65                 tmp |= t;
     66             }
     67             g[i][j] = tmp;
     68         }
     69     }
     70 }
     71 
     72 void get()
     73 {
     74     for(R i = 0; i <= maxn; i ++)
     75     {
     76         int x = 1;
     77         for(R j = 1; j <= n; j ++, x <<= 1)
     78         {
     79             if(i & x) continue;
     80             for(R k = 1; k <= n; k ++)
     81                 upmin(f[i | g[j][k]], f[i] + 1);
     82             break;
     83         }
     84     }
     85     printf("%d
    ", f[maxn]);
     86 }
     87 
     88 void work()
     89 {
     90     T = read();
     91     while(T --) 
     92         pre(), get();
     93 }
     94 
     95 int main()
     96 {
     97 //    freopen("in.in", "r", stdin);
     98     work();
     99 //    fclose(stdin);
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    wp之动态初始屏幕
    C#实现简易ajax调用后台方法
    扩展JavaScriptSerializer之Camelcase属性名
    wp之切换图片动画
    JQuery.Ajax用法
    工欲善其事,必先利其器
    asp.net中使用自定义的config文件
    windows phone7 学习笔记15——Bing Maps
    wp7屏幕截图代码
    windows phone7 学习笔记13——Panorama和Pivot
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9760473.html
Copyright © 2020-2023  润新知