九度OJ(字符串、位移操作、背包、递归、dp栈模拟、八皇后)

/*
 九度 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;
}


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值