【日记】6.15

  今天上午的状态不是很好,就做了2道题,一个炮兵阵地,另一个是英文名字、具体忘了。

  下午的考试难度应该介于NOIp和NOI之间吧,感觉发挥的还行,已经做到我能做的极限了。

①导弹拦截,变成三维空间的了,而且要求的是最长上升序列的长,第一问很简单,和原来的一样,1D1D动态规划,需要注意的是导弹被拦截的顺序是可以改变的,例如拦截完第3个后可以再去拦第一个,所以要先对数据排序。

不过第二问就有点儿不一样了,因为要求的是最长上升序列,所以这个序列就不满足偏序关系了,也就是所谓的dilworth定理(最小链划分 = 最长反链),这个的证明可以找一本组合数学或离散数学去看看,或者去网上搜索下,其实我也只是知道了而已……没有打算会证明。那么第二问,我们来分析下,一个导弹被拦截了,如果不是这个上升序列的第一个,那么肯定有个前趋,最后的结果就是每个点都有覆盖,我们很容易就能想到的是二分图结构的最小路径覆盖,利用(最小路径覆盖=|P|-其中最大匹配数)就可以做出第二问了。

至于超了一组的原因,应该是求最大匹配的时候用的是最简单的算法,时间复杂度较高的原因。

bomba
  1 /**
  2 *Prob    : bomba
  3 *Data    : 2012-6-15
  4 *Sol    : ①动归 ②二分图
  5 *Author : ZhouHang
  6 */
  7 
  8 #include <cstdio>
  9 #include <algorithm>
 10 #include <cstring>
 11 
 12 #define MaxN 1100
 13 
 14 using namespace std;
 15 
 16 struct node
 17 {
 18     int x,y,z;
 19 } a[MaxN];
 20 int n,ans;
 21 int f[MaxN];
 22 //二分图
 23 int maxnum;
 24 int link[MaxN];
 25 bool v[MaxN];
 26 bool map[MaxN][MaxN];
 27 
 28 bool cmp(int i,int j)
 29 {
 30     if (a[i].x>a[j].x&&a[i].y>a[j].y&&a[i].z>a[j].z) return true;
 31     return false;
 32 }
 33 
 34 void Make_Graph()
 35 {
 36     memset(map,false,sizeof(map));
 37     for (int i=1; i<=n; i++)
 38      for (int j=1; j<=n; j++)
 39      {
 40         if (i==j) continue;
 41         if (cmp(i,j)) map[i][j]=true;
 42      }
 43 }
 44 
 45 bool find(int i)
 46 {
 47     for (int k=1; k<=n; k++)
 48         if ( (!v[k])&&map[i][k] )
 49         {
 50             v[k]=true;
 51             if ( link[k]==0||find(link[k]) )
 52             {
 53                 link[k]=i;
 54                 return true;
 55             }
 56         }
 57     return false;
 58 }
 59 
 60 void work()
 61 {
 62     maxnum=0;
 63     for (int i=1; i<=n; i++)
 64     {
 65         memset(v,false,sizeof(v));
 66         if ( find(i) ) maxnum++;
 67     }
 68 }
 69 
 70 void Swap(node &i,node &j)
 71 {
 72     node c=i;
 73     i=j; j=c;
 74 }
 75 
 76 bool check(int i,int j)
 77 {
 78     if (a[i].x>a[j].x) return true;
 79     if (a[i].x<a[j].x) return false;
 80     if (a[i].y>a[j].y) return true;
 81     if (a[i].y<a[j].y) return false;
 82     if (a[i].z>a[j].z) return true;
 83     return false;
 84 }
 85 
 86 int main()
 87 {
 88     freopen("bomba.in","r",stdin);
 89     freopen("bomba.out","w",stdout);
 90     
 91     scanf("%d",&n);
 92     for (int i=1; i<=n; i++)
 93         scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
 94     
 95     for (int i=1; i<=n; i++)
 96      for (int j=i+1; j<=n; j++)
 97      {
 98         if (check(i,j)) Swap(a[i],a[j]); 
 99      }
100 
101     //first question
102     for (int i=1; i<=n; i++) f[i]=1;
103     ans=1;
104     for (int x=2; x<=n; x++)
105      for (int y=1; y<x; y++)
106         if (cmp(x,y))
107         {
108             f[x]=max(f[x],f[y]+1);
109             if (f[x]>ans) ans=f[x];
110         }
111         
112     printf("%d\n",ans);
113     
114     //sencond question
115     Make_Graph();
116     memset(link,0,sizeof(link));
117     work();
118     printf("%d\n",n-maxnum);
119     
120     fclose(stdin); fclose(stdout);
121     return 0;
122 }

 

③新打鼹鼠

这道题我果断写了个最简单的动态规划,也就是最好想的一维动归f[i]=max(f[j])+w[i]时间复杂度是O(M2)的

这道题的dp是不满足决策单调性的,所以没有方法从动归的角度优化,就要去从别的方面考虑,或许把状态离散化成坐标的点会更好点,但是后面的我就想不到了,等待老师的集体报告。

posted @ 2012-06-16 11:36  守護N1身边  阅读(159)  评论(0编辑  收藏  举报