hdu4975 行列和构造矩阵(dp判断唯一性)
生活随笔
收集整理的這篇文章主要介紹了
hdu4975 行列和构造矩阵(dp判断唯一性)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 和hdu4888一樣,只不過是數據加強了,就是給你行列的和,讓你構造一個矩陣,然后判斷矩陣是否唯一。
思路:
? ? ? 和hdu4888一樣,只不過是數據加強了,就是給你行列的和,讓你構造一個矩陣,然后判斷矩陣是否唯一。
思路:
? ? ? 構造矩陣很簡單,跑一次最大流就行了,關鍵是判斷矩陣的唯一性,之前的那個4888我用的是深搜找環過的,這個題目就TLE了,數據加強了,對于判斷矩陣的唯一性我們可以這么想假如某一行的i列和j列滿足 i列的這個> 0 && j列的這個 < 9此時我們再在另一行找到 ? i列的這個< 9 && j列的這個 > 0就可以把>0 的拿出來一個放在<9的上面,這樣答案就不唯一了,對于最大流跑完后的到的矩陣,如果我們暴力判斷上面的哪些情況的話是大約O(n^4)這樣就比DFS找環還浪費時間,所以我們要用到dp優化,dp[i][j]記錄的是在當前的狀態之前,是否存在在某一行中,i列<9,j列>0,這樣我們就可以利用之前狀態的結果來節省一層for(具體看代碼),但是這樣還是TLE了,我們在每個for前面加幾個小優化就可以過了。
#include<stdio.h> #include<string.h> #include<queue>#define N_node 1005 #define N_edge 600000 #define INF 1000000000 using namespace std;typedef struct {int to ,next ,cost; }STAR;typedef struct {int t ,x; }DEP;STAR E[N_edge]; DEP xin ,tou; int list[N_node] ,listt[N_node] ,tot; int deep[N_node]; int row[505] ,col[505]; int map[505][505]; int dp[505][505];void add(int a ,int b ,int c) {E[++tot].to = b;E[tot].cost = c;E[tot].next = list[a];list[a] = tot;E[++tot].to = a;E[tot].cost = 0;E[tot].next = list[b];list[b] = tot; }bool BFS_Deep(int s ,int t ,int n) {memset(deep ,255 ,sizeof(deep));deep[s] = 0;xin.x = s ,xin.t = 0;queue<DEP>q;q.push(xin);while(!q.empty()){tou = q.front();q.pop();for(int k = list[tou.x] ;k ;k = E[k].next){xin.x = E[k].to;xin.t = tou.t + 1;if(deep[xin.x] != -1 || !E[k].cost)continue;deep[xin.x] = xin.t;q.push(xin);}}for(int i = 0 ;i <= n ;i ++)listt[i] = list[i];return deep[t] != -1; }int minn(int x ,int y) {return x < y ? x : y; }int DFS_Flow(int s ,int t ,int flow) {if(s == t) return flow;int nowflow = 0;for(int k = listt[s] ;k ;k = E[k].next){listt[s] = k;int to = E[k].to;int c = E[k].cost;if(deep[to] != deep[s] + 1 || !c)continue;int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));nowflow += tmp;E[k].cost -= tmp;E[k^1].cost += tmp;if(flow == nowflow)break; } if(!nowflow) deep[s] = 0;return nowflow; }int DINIC(int s ,int t ,int n) {int ans = 0;while(BFS_Deep(s ,t ,n)){ans += DFS_Flow(s ,t ,INF);}return ans; }bool jude(int n ,int m ,int mktot) {int i = 1 ,j = 1 ,k;for(k = mktot + 1 ;k <= tot ;k += 2){ map[i][j] = E[k].cost;if(++j > m) {i ++ ,j = 1;}} memset(dp ,0 ,sizeof(dp));for(i = 1 ;i <= n ;i ++){if(row[i] == 0 || m * 9 == row[i])continue;for(j = 1 ;j <= m ;j ++){if(col[j] == 0 || n * 9 == col[j])continue; for(k = j + 1 ;k <= m ;k ++){int mk1 = 0 ,mk2 = 0;if(map[i][j] < 9 && map[i][k] > 0){if(dp[k][j]) return 1;mk1 ++;}if(map[i][j] > 0 && map[i][k] < 9){if(dp[j][k]) return 1;mk2 ++;}if(mk1) dp[j][k] = 1;if(mk2) dp[k][j] = 1;}}}return 0; }int main () {int n ,m ,i ,j ,s1 ,s2 ,a ,mkk;int t ,cas = 1;scanf("%d" ,&t);while(t--){scanf("%d %d" ,&n ,&m);s1 = s2 = mkk = 0;memset(list ,0 ,sizeof(list)) ,tot = 1;for(i = 1 ;i <= n ;i ++){scanf("%d" ,&a);add(0 ,i ,a);s1 += a;if(m * 9 < a) mkk = 1;row[i] = a;}for(i = 1 ;i <= m ;i ++){scanf("%d" ,&a);add(i + n ,n + m + 1 ,a);s2 += a;col[i] = a;if(n * 9 < a) mkk = 1;}printf("Case #%d: " ,cas ++);if(s1 != s2 || mkk){puts("So naive!");continue;} int mktot = tot + 1; for(i = 1 ;i <= n ;i ++)for(j = 1 ;j <= m ;j ++)add(i ,j + n ,9);int maxflow = DINIC(0 ,n + m + 1 ,n + m + 1); if(s1 != maxflow){puts("So naive!");continue;} jude(n ,m ,mktot)? puts("So young!"):puts("So simple!");}return 0; }
總結
以上是生活随笔為你收集整理的hdu4975 行列和构造矩阵(dp判断唯一性)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu4971 流-最大权闭包
- 下一篇: hdu4974 简单题