题目链接:http://codeforces.com/contest/707/my
看了这位大神的详细分析,一下子明白了。链接:http://blog.csdn.net/queuelovestack/article/details/52269321
搞了两天,终于彻底理解了。本来觉得怎么也不可能和DFS扯上关系,结果以操作的编号建树,对于其他3个操作,直接dfs即可。
在执行操作④之后,书架的状态其实已经回到了之前的某种状态k那么,如果我们从状态k出发,直接去推算出所有经操作④会回到状态k的状态,这样整体就是一个树。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e3+5; 4 int n,m,k; 5 struct node 6 { 7 int x,y; 8 }; 9 node q[100005]; 10 vector<int> g[100005]; 11 int l[maxn][maxn]; 12 int op[100005]; 13 int ans[100005]; 14 void dfs(int u,int sum) 15 { 16 ans[u] = sum; 17 for(int i=0;i<g[u].size();i++) 18 { 19 int v = g[u][i]; 20 int opp = op[v]; 21 int x = q[v].x; 22 int y = q[v].y; 23 if(opp==1) 24 { 25 if(l[x][y]) 26 { 27 dfs(v,sum); 28 } 29 else 30 { 31 l[x][y] = 1; 32 dfs(v,sum+1); 33 l[x][y] = 0; 34 } 35 } 36 else if(opp==2) 37 { 38 if(!l[x][y]) 39 { 40 dfs(v,sum); 41 } 42 else 43 { 44 l[x][y] = 0; 45 dfs(v,sum-1); 46 l[x][y] = 1; 47 } 48 } 49 else if(opp==3) 50 { 51 int cur = 0; 52 for(int j=1;j<=m;j++) 53 { 54 if(l[x][j]) 55 { 56 l[x][j] = 0; 57 cur--; 58 } 59 else 60 { 61 l[x][j] = 1; 62 cur++; 63 } 64 } 65 dfs(v,sum+cur); 66 for(int j=1;j<=m;j++) 67 { 68 if(l[x][j]) l[x][j] = 0; 69 else l[x][j] = 1; 70 } 71 } 72 else 73 { 74 dfs(v,sum); 75 } 76 } 77 } 78 int main() 79 { 80 cin>>n>>m>>k; 81 for(int i=1;i<=k;i++) 82 { 83 int sel; 84 scanf("%d",&sel); 85 op[i] = sel; 86 if(sel!=4) 87 { 88 if(sel<=2) 89 { 90 scanf("%d %d",&q[i].x,&q[i].y); 91 g[i-1].push_back(i); 92 } 93 else 94 { 95 scanf("%d",&q[i].x); 96 g[i-1].push_back(i); 97 } 98 } 99 else 100 { 101 scanf("%d",&q[i].x); 102 g[q[i].x].push_back(i); 103 } 104 } 105 dfs(0,0); 106 for(int i=1;i<=k;i++) 107 { 108 printf("%d ",ans[i]); 109 } 110 return 0; 111 }