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

 Liaoning Ship’s Voyagec++

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

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

亲测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\n",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 Gamespa

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

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

如今能够优化一下,更改这个点以后的答案,分为两种状况,不包含这个点的最大子矩阵ans1,以及包含这个点的最大子矩阵ans2 - a[i][j] + x。ip

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

这算是一个放缩吧,get

若是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