1. 程式人生 > >分考場(超時一個點)

分考場(超時一個點)

algo void int size main break ring %d 存儲

#include<cstdio>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector> 
#include<string>
#include<queue>
#include<map>
#include<stack>
using namespace std; 
int d[105][105];        //d[i][j]=x 第i個教室 第j個學生編號x 
int cnt[105
]; int mp[105][105]; int minn = 10000000; //思路:遍歷所有情況,加入這個學生,或不加入這個學生,中途剪枝 int n,m; /* void dfs(int no,int tot) //目前有tot個教室,考慮將編號no的學生編入教室 { if(tot >= minn) return; //剪枝 if(no > n) { if(tot < minn) minn = tot; return; } int f1 = 0; for(int i=1;i<=tot;i++) { f1 = 0; for(int j=1;j<=n;j++) { if(d[i][j]==1) //第i間教室有個編號為j的學生 { if(mp[no][j] == 1) //j和no認識,no無法編入i教室 { f1 = 1; break; } } } if(f1 == 0) //第i間教室無人認識no { d[i][no]=1; dfs(no+1,tot); //編入no d[i][no]=0; //不編入no } } //仍無法編入no d[tot+1][no] = 1; dfs(no+1,tot+1); //已經得到無法編入no的情況下的教室數目 d[tot+1][no] = 0; //錯誤點,沒有重置 }
*/ //超時原因: d[i][j]=1 第i個教室 有編號為j的學生 ,這種存儲結構導致每次都需要遍歷n次 //改進方法: d[i][j]=x 第i個教室 第j個人的編號為x void dfs(int no,int tot) //目前有tot個教室,考慮將編號no的學生編入教室 { if(tot >= minn) return; //剪枝 if(no > n) { if(tot < minn) minn = tot; return; }
int ct = 0; for(int i=1;i<=tot;i++) { ct = 0; for(int j=1;j<=cnt[i];j++) //d[i][j]=x ,x為編號 { if(mp[no][d[i][j]] == 1) //x和no認識,no無法編入i教室 break; else ct++; } if(ct == cnt[i]) //第i間教室無人認識no { cnt[i]++; d[i][cnt[i]]=no; dfs(no+1,tot); //編入no cnt[i]--; //不編入no } } //仍無法編入no cnt[tot+1]++; d[tot+1][cnt[tot+1]] = no; dfs(no+1,tot+1); //已經得到無法編入no的情況下的教室數目 cnt[tot+1]--; //重置 } int main() { scanf("%d%d",&n,&m); memset(mp,0,sizeof(mp)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { cnt[i] = 0; for(int j=1;j<=n;j++) { mp[i][j] = 0; d[i][j] = 0; } } for(int i=1;i<=m;i++) { int a,b; scanf("%d %d",&a,&b); mp[a][b] = 1; mp[b][a] = 1; } dfs(1,1); printf("%d",minn); return 0; }

分考場(超時一個點)