• EC复建补题,补掉北京赛场上卡的两个题。 Liaoning Ship’s Voyage 和 Puzzle Game


     Liaoning Ship’s Voyage

    一个只有20×20的矩阵上面进行bfs求最短路,为了增加难度,上面随便画一个三角形,被称作百慕大三角,八联通的走,不能进入三角形,问最短路。

    直接bfs,判断可不可行的时候用,暴力将八联通线段拆成(X)段,看点是否在三角形内即可。

    亲测X = 100就行。

     1 #include <bits/stdc++.h>
     2 const long long mod = 1e9+7;
     3 const double eps = 1e-8;
     4 #define inf 0x3f3f3f3f
     5 using namespace std;
     6 typedef pair<double,double> pdd;
     7 pair <double,double>a,b,c;
     8 int vis[50][50],n;
     9 char ma[50][50];
    10 int dx[] = {1,-1,0,0,-1,-1,1,1};
    11 int dy[] = {0,0,1,-1,1,-1,1,-1};
    12 struct P{
    13     int x,y,step;
    14     P(){}
    15     P(int x,int y,int step):x(x),y(y),step(step){}
    16 };
    17 inline double cross(pdd a,pdd b){
    18     return a.first*b.second - a.second *b.first;
    19 }
    20 inline int sgn(double x){
    21     if (x > eps) return 1;
    22     else if (x < -eps ) return -1;
    23     return 0;
    24 }
    25 inline bool check(double xx,double yy){
    26     pdd V1 = make_pair(-xx+a.first,-yy+a.second);
    27     pdd V2 = make_pair(-xx+b.first,-yy+b.second);
    28     pdd V3 = make_pair(-xx+c.first,-yy+c.second);
    29     double res1 = cross(V1,V2);
    30     double res2 = cross(V2,V3);
    31     double res3 = cross(V3,V1);
    32     if (sgn(res1)>0&&sgn(res2) > 0 && sgn(res3) > 0) return false;
    33     else if (sgn(res1)<0&&sgn(res2) < 0 && sgn(res3) < 0) return false;
    34     return true;
    35 }
    36 int main()
    37 {
    38     while (scanf("%d",&n)!=EOF){
    39         scanf("%lf%lf%lf%lf%lf%lf",&a.first,&a.second,&b.first,&b.second,&c.first,&c.second);
    40         getchar();
    41         memset(vis,0,sizeof(vis));
    42         for (int i = n - 1 ; i >=0 ; i--){
    43             for (int j = 0 ; j < n  ;j++){
    44                 scanf("%c",&ma[j][i]);
    45             }
    46             getchar();
    47         }
    48         queue<P> que;
    49         if (ma[0][0]  == '#') {puts("-1");continue;}
    50         vis[0][0] = 1;
    51         que.push(P(0,0,0));
    52         int flag = 0;
    53         while (!que.empty()){
    54             P now = que.front();
    55             que.pop();
    56             if (now.x == n - 1 && now.y == n-1){
    57                 flag = 1;printf("%d
    ",now.step);break;
    58             }
    59             for (int i = 0 ; i < 8 ; i++){
    60                 int xx = now.x + dx[i];
    61                 int yy = now.y + dy[i];
    62                 if (xx < 0 || yy  < 0 ||xx >=n || yy >=n) continue;
    63                 if (ma[xx][yy] =='#') continue;
    64                 double tmpx = now.x,tmpy = now.y;
    65                 double addx = 1.0 * dx[i]/100.0;
    66                 double addy = 1.0 * dy[i]/100.0;
    67                 int flag2 = 1;
    68                 for (int j = 1;j <=100; j++){
    69                     if (check(tmpx,tmpy) == 0){
    70                         flag2 = 0;break;
    71                     }
    72                     tmpx +=addx;tmpy +=addy;
    73                 }
    74                 if (flag2 ==0)continue;
    75                 if (vis[xx][yy] ==0){
    76                     P nex = P(xx,yy,now.step+1);
    77                     que.push(nex);
    78                     vis[xx][yy] = 1;
    79                 }
    80             }
    81         }
    82         if (flag == 0) puts("-1");
    83     }
    84     return 0;
    85 }
    View Code

    Puzzle Game

    最多更改矩阵中的一个点变为x,最小化,最大矩阵和。

    这个 暴力算法是枚举 更改哪个点,然后求最大矩阵和。

    现在可以优化一下,更改这个点之后的答案,分为两种情况,不包含这个点的最大子矩阵ans1,以及包含这个点的最大子矩阵ans2 - a[i][j] + x。

    包含这个点的最大子矩阵怎么算呢?

    这算是一个放缩吧,

    如果max为包含这个点的矩阵和,那么 答案显然为ans2 = max

    如果max不是呢?肯定存在别的矩阵为max,那么ans2是谁多大也就没有意义了,并且max - a[i][j] + x 是显然小于 max的(因为我们前面continue掉了)。

     1 #include <bits/stdc++.h>
     2 #define inf 0x3f3f3f3f
     3 using namespace std;
     4 int ans[5][200];
     5 int a[200][200];
     6 int sum[200];
     7 int main()
     8 {
     9     int n,m,tmp;
    10     //freopen("in.txt","r",stdin);
    11     while (cin >> n >> m >> tmp){
    12         memset(a,0,sizeof(a));
    13         for (int i = 1 ; i <= n ; i++){
    14             for (int j =  1; j <= m ; j++){
    15                 scanf("%d",&a[i][j]);
    16             }
    17         }
    18         for (int j = 0 ; j<=180 ; j++)
    19             ans[0][j] = ans[1][j] = ans[2][j] = ans[3][j] = -inf;
    20 
    21         for (int i = 1 ; i <=n; i++){
    22             memset(sum,0,sizeof(sum));
    23             for (int j = i ; j<=n; j++){
    24                 for (int t = 1; t <= m ; t++) sum[t] += a[j][t];
    25                 int tsum = 0;
    26                 int la = 0;
    27                 int tans = -inf;
    28                 for (int k = 1; k <= m; k++){
    29                     while (tsum < 0) tsum -= sum[la],la++;
    30                     tsum += sum[k];
    31                     tans = max(tans,tsum);
    32                 }
    33                 ans[0][i] = max(ans[0][i],tans);
    34                 ans[1][j] = max(ans[1][j],tans);
    35             }
    36         }
    37         for (int i = 1 ; i <=m; i++){
    38             memset(sum,0,sizeof(sum));
    39             for (int j = i ; j<=m; j++){
    40                 for (int t = 1; t <= n ; t++) sum[t] += a[t][j];
    41                 int tsum = 0;
    42                 int la = 0;
    43                 int tans = -inf;
    44                 for (int k = 1; k <= n; k++){
    45                     while (tsum < 0) tsum -= sum[la],la++;
    46                     tsum += sum[k];
    47                     tans = max(tans,tsum);
    48                 }
    49                 ans[2][i] = max(ans[2][i],tans);
    50                 ans[3][j] = max(ans[3][j],tans);
    51             }
    52         }
    53         for (int i = n ; i >=1 ; i--) ans[0][i] = max(ans[0][i],ans[0][i+1]);
    54         for (int i = m ; i >=1 ; i--) ans[2][i] = max(ans[2][i],ans[2][i+1]);
    55         for (int i = 1 ; i <=n ; i++) ans[1][i] = max(ans[1][i],ans[1][i-1]);
    56         for (int i = 1 ; i <=m ; i++) ans[3][i] = max(ans[3][i],ans[3][i-1]);
    57         int res = ans[0][1];
    58         for (int i = 1 ;  i <= n ;i++){
    59             for (int j = 1 ; j <= m ; j++){
    60                 if (a[i][j] < tmp) continue;
    61                 int tres = ans[0][1] - a[i][j] + tmp;
    62                 tres = max(tres,ans[0][i+1]);
    63                 tres = max(tres,ans[1][i-1]);
    64                 tres = max(tres,ans[2][j+1]);
    65                 tres = max(tres,ans[3][j-1]);
    66                 //cout << tres <<" " << i <<" " << j << endl;
    67                 //cout << ans[0][i+1] <<" " <<ans[1][i-1] <<" " << ans[2][j+1] <<" "<< ans[3][j-1] << endl;
    68                 res = min(res,tres);
    69             }
    70         }
    71         cout << res  << endl;
    72     }
    73 
    74 }
    View Code
  • 相关阅读:
    AspNetPager.dll 分页控件使用方法、含有代码示例 [转]
    XmlDocument序列化到Session[转]
    静态构造函数
    错误日志[常用方法]
    Vss 源代码管理中的目录问题
    StopWatch 获得更精确的运行时间
    最近写的一个验证码.
    windowsservice 中的 currentdirectory
    vs2005常用快捷键(转贴)
    一个mapyEasy 图片切割工具 及源码
  • 原文地址:https://www.cnblogs.com/HITLJR/p/7912140.html
Copyright © 2020-2023  润新知