A.Beautiful Matrix
如果1的位置在Matrix中为x,y(从1开始计数),答案为abs(3-x)+abs(3-y)
B.Squares
满足所选的点要包含在对角点(0,0)到(ai,ai)这样的刚好k个正方形内(边界也算),降序sort一遍a数组,输出(a[k-1],a[k-1])或者(a[k-1],0)什么的都行
C.Circle of Numbers
构造出满足题意的序列就可以,因为不限制排列开始的元素位置,不限制顺时或是逆时,所以直接可以让1是第一个元素,tutorial里的方法是分情况判断构造出第二三个元素,然后依约束的关系去恢复剩下的元素。刚开始要去判断每个元素是否仅仅出现的4次,否则-1.
这里我用的dfs+回溯的方法来做,虽然元素很多,但是每个元素相连接的点只有4个,还比较快。
用vis数组标记使用过的元素
对于Ans中只有1个元素时候,第2个元素需要满足,link[1]中包含元素2,搜的时候就是按照邻接关系来搜的,这是必然的。
对于Ans中多于1个元素的时候,每添加一个新元素,如 A B C(Prepare to add),需要约束条件link[A]中包含A、C,link[B]中包含C.
不断的搜索直到Ans的大小为n时,答案就有了。
但是某些组合满足每个元素都出现4次,但是也可能构造不出圈,所以我对于那些没有printf出答案然后exit(0)的数据,后面补一个-1.

vector<int> link[100005]; int cnt[100005]; int vis[100005]; vector<int> ans; int n; int has(vector<int> e, int val) { for(int i = 0; i < e.size(); i++) if(e[i] == val) return 1; return false; } void dfs(int val) { int i; vis[val] = 1; ans.push_back(val); // for(i = 0;i < ans.size(); i++) // printf("%d ", ans[i]); // printf("\n"); if(ans.size() == n) { for(i = 0;i < n; i++) printf("%d ", ans[i]); printf("\n"); exit(0); } for(i = 0; i < link[val].size(); i++) { if(!vis[ link[val][i] ] && ans.size() <= 1) { dfs( link[val][i] ); vis[ link[val][i] ] = 0; ans.pop_back(); } else if(!vis[ link[val][i] ] && ans.size() >= 2) { if(has( link[ ans[ ans.size()-2 ] ], ans[ ans.size()-1 ] ) && has(link[ ans[ans.size()-2] ], link[val][i]) && has( link[ ans[ ans.size()-1 ] ], link[val][i]) ) { dfs( link[val][i] ); vis[ link[val][i] ] = 0; ans.pop_back(); } } } } int main() { int a,b,i; get(n); memset(cnt,0,sizeof(cnt)); memset(vis,0,sizeof(vis)); for(i = 0; i < 2*n; i++) { get(a);get(b); cnt[a]++; cnt[b]++; link[a].push_back(b); link[b].push_back(a); } int ok = 1; for(i = 1; i <= n; i++) { if(cnt[i] != 4) { ok = 0; break; } } if(!ok) printf("-1\n"); else { dfs(1); printf("-1\n"); } return 0; }
D.Cycle in Graph
给一个无向图,求某个输出某个环,长度 ≥ k+1.
如果存在一条路径v1,v2,...,vr,若vr的相邻点中包括v1,那么就至少形成了一个长度为r的环,只要r ≥ k+1满足题意输出答案就可以了。
用DFS+回溯的方法去搜索这样可能的路径。

/*
DFS+回溯,找出大于等于k+1的环。
*/
vector< int > adj[100005];
vector< int > path;
int vis[100005];
int k;
void dfs(int cur,int len)
{
int i,j;
path.push_back(cur);
vis[cur] = 1;
len++;
if(len >= k+1)
{
for(i = 0; i < adj[cur].size(); i++)
{
if(adj[cur][i] == path[0])
{
printf("%d\n", len);
for(j = 0; j < path.size(); j++)
printf("%d ", path[j]);
printf("\n");
exit(0);
}
}
}
for(i = 0; i < adj[cur].size(); i++)
{
if(!vis[adj[cur][i]]) dfs(adj[cur][i],len);
}
vis[cur] = 0;
path.pop_back();
}
int main()
{
int a,b,i,m,n;
get(n);get(m);get(k);
memset(vis,0,sizeof(vis));
for(i = 1; i <= m; i++)
{
get(a);get(b);
adj[a].push_back(b);
adj[b].push_back(a);
}
for(i = 1; i <= n; i++)
dfs(i,0);
return 0;
}
E.Rhombus
解题的方法,就和题目意思一样,从菱形的角度来考虑。
≥ 0, 而
是坐标(i, j)到坐标(x, y)的曼哈顿距离,约束出来是一个菱形。
当k = 2时候,这个式子在(x,y)处表达的图案如下
在该点处f(x,y) = 2*ax,y + 1*(ax-1,y-1 + ax+1,y-1 + ax-1,y+1 + ax+1,y+1) , 所以依次类推。
把菱形按照距离相关的权值,从大到小把菱形分圈,每个权值圈,找出它的ai,j的总和,然后在和权值运算。
可以数组记录,斜左下,斜右下的递增和,这样求菱形每一遍和时候,每一段只用O(1)就可以求出。
最后brute force,遍历能取的所有位置,记录最大值出现位置。
搓方法,O(n3),2781ms跑完所有数据,接近超时了。Tutorial 方法更好一些。

#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <sstream> #include <iomanip> #include <vector> #include <deque> #include <list> #include <set> #include <map> #include <stack> #include <queue> #include <bitset> #include <string> #include <numeric> #include <functional> #include <iterator> #include <typeinfo> #include <utility> #include <memory> #include <cmath> #include <cstdlib> #include <cctype> #include <cstddef> #include <complex> #include <ctime> #include <cassert> using namespace std; typedef __int64 LL; static inline bool get(int &v) { int s = 1, c; while(!isdigit(c = getchar())&&c != '-') { if(c == EOF) break ; } if(c == EOF) return 0; if(c == '-') s = 0 , v = 0; else v = c^48; for(;isdigit(c = getchar());v = (v << 1) + (v << 3) + (c ^ 48)); v = (s ? v : -v); return 1 ; } struct st { int val; LL l; LL r; }matrix[1005][1005]; void init(int n,int m) { int i, j; for(i = 0; i <= n; i++) { for(j = 0; j <= m+1; j++) { matrix[i][j].val = 0; matrix[i][j].l = 0; matrix[i][j].r = 0; } } } int main() { int n,m,k,i,j,v,a,b; get(n);get(m);get(k); init(n,m); for(i = 1; i <= n; i++) { for(j = 1; j <= m; j++) { get(matrix[i][j].val); matrix[i][j].l = matrix[i-1][j+1].l + matrix[i][j].val; matrix[i][j].r = matrix[i-1][j-1].r + matrix[i][j].val; } } LL ans = 0; a = k; b = k; for(i = k; i <= n-k+1; i++) for(j = k; j <= m-k+1; j++) { LL res = 0; for(v = k; v >= 1; v--) { if(v == k) { res += k*matrix[i][j].val; } else { LL tmp = 0; tmp += matrix[i][j-(k-v)].l - matrix[i-(k-v)][j].l; tmp += matrix[i+(k-v)][j].l - matrix[i][j+(k-v)].l; tmp += matrix[i+(k-v)][j].r - matrix[i][j-(k-v)].r; tmp += matrix[i][j+(k-v)].r - matrix[i-(k-v)][j].r; tmp += matrix[i-(k-v)][j].val; tmp -= matrix[i+(k-v)][j].val; res += v*tmp; } } //printf("%d\n" ,res); if(res > ans) { ans = res; a = i; b = j; } } printf("%d %d\n", a,b); return 0; }