/*
九度 http://ac.jobdu.com/graoldexamset.php
1149 子串计算:map、字符串库函数的使用
1151 位操作练习:pow、移位操作>>/<<
1152 点菜问题:背包,递归、dp,分为第i个装或不装
1153 括号匹配:栈模拟
1139 最大子矩阵:类似最大子段和。 O(n^3)复杂度
1140 八皇后:递归、
*/
/*
1149 子串计算 set集合的使用 string/set<string>::itrator p = set1.begin();
思路一:把所有子串都保存下来,之后排序(有重复的),之后使用while循环,依次查找即可。while(strcmp(str[i],str[i+1])==0) count++;i++;
思路二:先找出所有不重复的子串,排序;之后在原串中依次查找所有子串出现的次数,统计输出即可。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 1000100
string str;
vector<string> vec1;
set<string> set1; //set multisets 默认是排好序的,一个包含元素唯一、一个包含元素不唯一。
int main() {
freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
while(cin>>str){
//使用C++的set、vector等,一定要注意清空!
vec1.clear();set1.clear();
int len = (int)str.length();
for(int i=0;i<len;i++){
for(int j=1;j<=len-i;j++){//注意 这里substr的第二个参数为length / j的长度需要-i!
vec1.push_back(str.substr(i,j));
set1.insert(str.substr(i,j)); //默认元素不重复,且同时会排好序
// cout<<str.substr(i,j)<<endl;
}
}
for(set<string>::iterator p = set1.begin();p!=set1.end();p++){
int count = 0;
for(vector<string>::iterator k = vec1.begin();k!=vec1.end();k++){
if((*k)==(*p)) count++;
}
if(count>1){
cout<<(*p)<<" "<<count<<endl;
}
}
}
return 0;
}
//之后在网上看到另一种更好的方法:使用map即可 速度快了5倍左右
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main(){
map<string,int> M;
map<string,int>::iterator it;
string str,subStr;
int len;
while( cin>>str ){
len = str.length();
for( int i=1;i<len;i++){
for( int j=0;j<len-i+1;j++){
subStr = str.substr(j,i);
M[ subStr ]++;
}
}
for( it=M.begin(); it!=M.end(); it++){
if( it->second>1)
cout<<it->first<<" "<<it->second<<endl;
}
M.clear();
}
return 0;
}
*/
/*
1151 位操作练习 pow、位移操作>>/<<
简单题
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 1000100
int main() {
freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
int n;
scanf("%d",&n);
while(n--){
int a,b;scanf("%d %d",&a,&b);
int len = 0;int flag=0;int low = (int)pow(2,15);
while((len++)<=16){
if(a==b){flag=1; break;}
if(a%2) a = low+(a>>1);
else a = (a>>1);
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
*/
/*
1152 点菜问题:递归、dp、按照第i个菜点或不点来进行
//方法一:递归、超时
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 1010
typedef struct LNode{
int a,b;
}LNode;
LNode node[N];
int c,n;
int dfs(int money,int cur){
if(cur>=n) return 0;
if(money + node[cur].a >= c) return 0;
else return max(node[cur].b + dfs(money+node[cur].a,cur+1),dfs(money,cur+1));
}
int main() {
//freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
while(scanf("%d %d",&c,&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d %d",&node[i].a,&node[i].b);
}
printf("%d\n",dfs(0,0));
}
return 0;
}
//改为dp,AC 注意这里菜的价格需要按照从大到小的顺序进行
for(int j=c;j>=node[i].a;j--){ // j>=node[i].a 是为了保证下面dp[]数组访问不会越界!
if(node[i].b + dp[j-node[i].a] > dp[j])
dp[j] = node[i].b + dp[j-node[i].a];
}
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 1010
typedef struct LNode{
int a,b;
}LNode;
LNode node[N];
int c,n;
int dp[N];
int main() {
//freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
while(scanf("%d %d",&c,&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%d %d",&node[i].a,&node[i].b);
}
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++){ //dp[i][j] 表示前i个物品,报销额度在j元之内 评价分数最高
for(int j=c;j>=node[i].a;j--){
if(node[i].b + dp[j-node[i].a] > dp[j])
dp[j] = node[i].b + dp[j-node[i].a];
}
}
int maxc = -1;
for(int i=0;i<N;i++){
if(dp[i]>maxc) maxc = dp[i];
}
printf("%d\n",maxc);
}
return 0;
}
*/
/*
1153 括号匹配:栈模拟 简单题 注意栈和正常序列是反着的!!!
注意! 因为判空 q.empty() RE了2次!
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 1010
char str[N];
typedef struct LNode{
char t;
int pos;
}LNode;
stack<LNode> q,q2;
int main() {
//freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
while(scanf("%s",str)!=EOF){
while(!q.empty()) q.pop();
while(!q2.empty()) q2.pop();
int len = (int)strlen(str);
for(int i=0;i<len;i++){
if(!q.empty() && q.top().t=='(' && str[i]==')'){
q.pop();
}else{
LNode n;
n.t = str[i];
n.pos = i;
if(n.t=='(' || n.t==')'){
q.push(n);
}
}
}//压栈的即为没有匹配的
for(int i=len-1;i>=0;i--){
if(!q.empty() && q.top().pos==i){
q2.push(q.top());
q.pop();
}
}
printf("%s\n",str);
for(int i=0;i<len;i++){
if(!q2.empty() && q2.top().pos==i){
if(q2.top().t=='(') printf("$");
else printf("?");
q2.pop();
}else printf(" ");
}printf("\n");
}
return 0;
}
*/
/*
1139 最大子矩阵和
方法:和最大子段和类似,可以先将竖着的包含哪些行的子矩阵列出来, 求和合并成一行,之后进行最大子段和
总的复杂度: O(n^3)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 1010
int f[N][N];
int dp[N][N];
int main() {
//freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
scanf("%d",&f[i][j]);
}
for(int j=1;j<=n;j++){
for(int i=1;i<=n;i++){
f[i][j] += f[i-1][j];
}
}
int maxc = -(2<<29);
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){ //代表从第i行到第j行
//合并成一行(每一列求和)
int dp[N]; memset(dp,0,sizeof(dp));
for(int k=1;k<=n;k++){
dp[k] = f[j][k] - f[i-1][k];
}
for(int k=1;k<=n;k++){ //以dp数组,进行最大子段和求解
dp[k] = max(dp[k-1] + dp[k],dp[k]);
maxc = max(maxc,dp[k]);
}
}
}
printf("%d\n",maxc);
}
return 0;
}
*/
/*
八皇后问题: 递归、回溯
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 11
int A[N];
int vis[N][N];
int answer[1010][N];
int tot=0;
int check(int i,int cur){
int num=0;
for(int ii=1;ii<=8;ii++){
if(vis[i][ii]) num++; //同行
}
for(int ii=1;ii<=8;ii++){
if(vis[ii][cur]) num++; //同列 --- 这里同行同列不能一起算,会少算次数!
}
if(num>2) return 0;
int a,b;
a = i; b = cur;
while(a>1 && b>1){
if(vis[--a][--b]) return 0;
}
a = i; b = cur;
while(a<8 && b<8){
if(vis[++a][++b]) return 0;
}
//右对角线
a = i; b = cur;
while(a>1 && b<8){
if(vis[--a][++b]) return 0;
}
a = i; b = cur;
while(a<8 && b>1){
if(vis[++a][--b]) return 0;
}
return 1;
}
void dfs(int cur){
if(cur==9){
tot++;
for(int i=1;i<=8;i++){
for(int j=1;j<=8;j++)
if(vis[i][j]){
answer[tot][i] = j;
break;
}
}
}else{
for(int i=1;i<=8;i++){
if(vis[cur][i]==0){ //当前行,第i个位置没有皇后
vis[cur][i]=1; //尝试在此位置放皇后
//检查时候合理
if(check(cur,i)){
dfs(cur+1);
}
// else printf("%d不合理 ",i);
vis[cur][i]=0; //回溯
}
}
}
}
int main() {
//freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
int T;scanf("%d",&T);
dfs(1);
while(T--){
int n;
scanf("%d",&n);
for(int i=1;i<=8;i++)
printf("%d",answer[n][i]);
printf("\n");
}
return 0;
}
<pre name="code" class="cpp">// 排列枚举: 类似八皇后、这里vis数组为一维。 递归进行即可
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define N 1010
int n;
int vis[N];
int A[N];
void print(int *a,int cur){
if(cur==n+1){
for(int i=1;i<=n;i++) printf("%d",a[i]);
printf("\n");
}else{
for(int i=1;i<=n;i++){
if(vis[i]==0){
vis[i]=1;
a[cur]=i;
print(a,cur+1);
vis[i]=0;
}
}
}
}
int main() {
freopen("/Users/a1/Public/20150717/20150717/in.txt","r",stdin);
scanf("%d",&n);
memset(vis,0,sizeof(vis));
print(A,1);
printf("ok\n");
return 0;
}