EOF使用:
MAC系统:输入结束后需要—>回车键—>(control+D)。即可结束输入。
windows系统:输入结束后需要—>回车键—>(control+Z)—>回车键
C++ 这里的 = 拷贝是值拷贝,会得到一个新的数组
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
// C++ 这里的 = 拷贝是值拷贝,会得到一个新的数组
auto matrix_new = matrix;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
matrix_new[j][n - i - 1] = matrix[i][j];
}
}
// 这里也是值拷贝
matrix = matrix_new;
}
};
begin()函数和end()位于iteartor;
而front()和back()位于vector list deque and etc…
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> v1;
vector<char>::iterator iter1;
vector<char>::iterator iter2;
v1.push_back('a');
v1.push_back('b');
v1.push_back('c');
v1.push_back('d');
cout << "v1.front() = " << v1.front() << endl;
cout << "v1.back() = " << v1.back() << endl;
iter1 = v1.begin();
cout << *iter1 << endl;
iter2 = v1.end()-1;
//v1.end()指向的是最后一个元素的下一个位置,所以访问最后一个元素,所以:iter2 = v1.end() - 1 是使iter2指向最后一个元素
cout << *iter2 << endl;
return 0;
}
C++ 标准模版库STL
除开vector和string之外的STL容器都不支持*(it+i)的访问方式
vector:向量/变长数组
Vector<类型>标识符(最大容量,初始所有值)
以及vector< vector<int> > dp(m, vector<int>(n) )
常见定义方法:(1) vector<int> a(5); //定义了5个整型元素的向量(<>中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的。
(2)vector<int> a(5,1); //定义了5个整型元素的向量,且给出每个元素的初值为1
(3)vector<int> a(b); //用b向量来创建a向量,整体复制性赋值
(4)vector<int> a(b.begin(),b.begin+3); //定义了a值为b中第0个到第2个(共3个)元素
(5)int b[7]={1,2,3,4,5,9,8};
vector<int> a(b,b+7); //从数组中获得初值
vector< vector<int> > v(m, vector<int>(n) );定义了一个vector容器,元素类型为vector<int>,初始化为包含m个vector<int>对象,每个对象都是一个新创立的vector<int>对象的拷贝,而这个新创立的vector<int>对象被初始化为包含n个0。
#include<vector>
using namespace std;
定义:
vector<int> name;
vector<int> vi[100];
vector<vector<int> > name;
访问:
下标 vi[index]
迭代器 vector<int>::iterator it = vi.begin();
通过*it来访问vector里的元素
函数:
push_back()
pop_back()
size()
clear()
insert(it,x)
erase()
set:集合 内部自动有序且不含重复元素
#include<set>
using namespace std;
定义:
set<int> name;
访问:
迭代器 set<int>::iterator it;
通过*it来访问set里的元素
函数:
insert()
find(value) 返回set中对应值为value的迭代器
erase()
size()
clear()
string字符串:
#include<string>
using namespace std;
定义: string str;
访问:
下标:str[i]
如果要读入和输出整个字符串,则只能用cin和cout
迭代器: string::iterator it;
函数:
operator+=
str1+=str2; //将str2直接拼接到str1上
length()/size()
insert()
erase()
clear()
substr()
string::npos:-1
find()
replace()
map映射:map会以键从小到大的顺序自动排序,map的键和值是唯一的
#include<map>
using namespace std;
定义:
map<string,int> mp;
访问:
下标:mp['c']
迭代器 map<char,int>::iterator it;
通过 it->first 来访问键 it->second来访问值
函数:
find(key) 返回键为key的映射的迭代器
erase()
size()
clear()
queue 队列:
#include<queue>
using namespace std;
queue<int> q;
push() pop()
front() back()
empty()
size()
priority_queue 优先队列:队首元素优先级最大
#include<queue>
using namespace std;
priority_queue<int> q;
push() pop()
top()
empty()
size()
priority_queue<int,vector<int>,greater<int> >q; //最小的元素放在队首
struct fruit{
string name;
int price;
friend bool operator < (fruit f2,fruit f2){
return f1.price > f2.price;
}
};
stack 栈:
#include<stack>
using namespace std;
stack<int> st;
push() pop()
top()
empty()
size()
pair 一个内部有两个元素的结构体:
#include<utility>
using namespace std;
algorithm:
**sort(首元素地址,尾元素地址的下一个地址,cmp比较函数):**
#include<algorithm>
using namespace std;
在STL标准容器中,只有 vector向量、string字符串、deque队列 是可以使用sort的
**#include <numeric>:**
accumulate(a,b,c)累加求和:
a为起始地址,b为结束地址,c为初始值
#include <numeric>
vector<int> v={1,2,3,4};
int sum = accumulate(v.begin(),v.end(),0);
C++和C:
C++中有string类型;len=str.length()
C语言中没有单独一种基本数据类型可以存储字符串,只能使用字符数组的方式。(字符串常量可以作为初值赋给字符数组,并使用%s的格式输出);len=strlen(str)
char str[4]=“abcd”;
printf("%s",str);
C++可以直接使用布尔型;
C语言中必须添加stdbool.h头文件才可以使用
C语言中不允许在for语句的表达式A里定义变量;
C++中可以
for(int i=1;i<=100;i++){
sum=sum+i;
}
C++:
引用:对引用变量的操作就是对原变量的操作(引用不是取地址)
void change(int &x){
x=1;
}
C:malloc free
C++:new delete
C++:
头文件:
#include<stdio.h> #include(C++)
输入:
scanf("%d",&n);
scanf("%lld",&n); //long long
scanf("%s",str);
scanf("%f",&f); //float
scanf("%lf",&db); //double
输出:
printf("%d",n);
printf("%lld",n); //long long
printf("%f",fl); //float
printf("%f",db); //double
sscanf(str,"%d",&n):把字符数组str中的内容以"%d"的格式写到n中
sprintf(str,"%d",n):把n以"%d"的格式写到str字符数组中
%f是float和double型的输出格式
转义字符:\n \t \0
a^b:位异或
scanf("%s",str);
printf("%s",str);
getchar():输入单个字符,可以识别换行符
putchar():输出单个字符
gets():输入一行字符串
puts():输出一行字符串
注:
scanf输入时:
%c格式能识别空格跟换行并将其输入;
%s通过空格或换行来识别一个字符串的结束
gets()识别换行符\n作为输入结束
注释:/* */ 或 //
math函数
#include<math.h>
fabs(double x):取绝对值
floor(double x):向下取整
ceil(double x):向上取整
pow(double x,double y):x^y
sqrt(double x):算术平方根
log(double x):以自然对数e为底的对数
round(double x):四舍五入,返回类型也是double型,需进行取整
const double pi=acos(-1.0);
#include<string.h>
memset(a,0,sizeof(a)); //赋值0或-1
strlen(str):长度
strcmp():返回两个字符串大小的比较结果
strcpy():复制
strcat():连接
生成随机数据:P144
[a,b]:rand()%(b-a+1)+a
[a,b],b>RAND_MAX:(int)round(1.0rand()/RAND_MAX(b-a)+a)
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
srand((unsigned)time(NULL));
for(int i=0;i<10;i++){
printf("%d ",(int)(round(1.0*rand()/RAND_MAX*50+10))); //随机数[10,60]
}
return 0;
}
switch语句
switch(表达式){
case 常量表达式1:
……
break;
case 常量表达式n:
……
break;
default:
……
}
数组:
一维数组:
int a[10]={5,3,2,6,8,4};
int a[10]={} //都赋初值0
数组作为函数参数时:
参数中数组的第一维不需要填写长度(如果是二维数组,那么第二维需要填写长度),实际调用时也只需填写数组名;
在函数中对数组元素的修改就等同于是对原数组元素的修改(这与普通的局部变量不同)P59
指针:
指针指向内存地址
只要在变量前面加上&,就表示变量的地址
指针变量用来存放指针
数组的名称作为数组的首地址使用 a==&a[0]
a+i==&a[i] *(a+i)==a[i]
两个int型的指针相减,等价于在求两个指针之间相差了几个int
int a;
int* p=&a; //地址&a赋值给p,*p获得a的值
结构体:
struct studentInfo{
int id;
char name[20];
studentInfo *next;
}stu,*p;
//访问变量
stu.id
p->id
#include<stdio.h>
struct Point{
int x,y;
Point(){} //用以不经初始化地定义pt[10]
Point(int _x,int _y):x(_x),y(_y){} //用以提供x和y的初始化
}pt[10];
int main(){
int num=0;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
pt[num++]=Point(i,j); //直接使用构造函数
}
}
for(int i=0;i<num;i++){
printf("%d,%d\n",pt[i].x,pt[i].y);
}
return 0;
}
代码实例
简单:
//PAT B1032 挖掘机技术哪家强 P86
#include<stdio.h>
const int maxn=100010;
int school[maxn]={0};
int main(){
int n,schID,score;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d %d",&schID,&score);
school[schID]+=score;
}
int k=1,MAX=-1;
for(int i=1;i<=n;i++){
if(school[i]>MAX){
MAX=school[i];
k=i;
}
}
printf("%d %d\n",k,MAX);
return 0;
}
中等:
//冒泡排序
#include<stdio.h>
int main(){
int a[10]={3,1,4,5,2};
for(int i=1;i<=4;i++){ //循环4次
for(int j=0;j<5-i;j++){
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int k=0;k<5;k++){
printf("%d ",a[k]);
}
return 0;
}
//PAT B1020 月饼 P118
#include<stdio.h>
#include<algorithm>
using namespace std;
struct mooncake{
double store; //库存量
double sell; //总售价
double price; //单价
}cake[1010];
bool cmp(mooncake a,mooncake b){ //按单价从高到低排序
return a.price>b.price;
}
int main(){
int n;
double D;
scanf("%d%lf",&n,&D);
for(int i=0;i<n;i++){
scanf("%lf",&cake[i].store);
}
for(int i=0;i<n;i++){
scanf("%lf",&cake[i].sell);
cake[i].price=cake[i].sell/cake[i].store; //计算单价
}
sort(cake,cake+n,cmp); //按单价从高到低排序
double ans=0; //收益
for(int i=0;i<n;i++){
if(cake[i].store<=D){ //如果需求量高于月饼库存量
ans+=cake[i].sell;
D-=cake[i].store;
}else{ //如果月饼库存量高于需求量
ans+=D*cake[i].price;
break;
}
}
printf("%.2f\n",ans);
return 0;
}
//PAT B1019/A1069 数字黑洞 P152
#include<stdio.h>
#include<algorithm>
using namespace std;
bool cmp(int a,int b){
return a>b;
}
void to_array(int n,int num[]){ //将n中每一位存到num数组中
for(int i=0;i<4;i++){
num[i]=n%10;
n=n/10;
}
}
int to_number(int num[]){ //将num数组转换为数字
int sum=0;
for(int i=0;i<4;i++){
sum=sum*10+num[i];
}
return sum;
}
int main(){
int n,MIN,MAX; //MIN和MAX分别表示递增排序和递减排序后得到的最小值和最大值
scanf("%d",&n);
int num[5];
while(1){
to_array(n,num);
sort(num,num+4);
MIN=to_number(num);
sort(num,num+4,cmp);
MAX=to_number(num);
n=MAX-MIN;
printf("%04d-%04d=%04d\n",MAX,MIN,n);
if(n==0 || n==6174) break; //退出
}
return 0;
}
复杂:
//日期差值P91
#include<stdio.h>
int month[13][2]={ //平年和闰年的每个月的天数
{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},
{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}
};
bool isLeap(int year){ //判断是否是闰年
return (year%4==0 && year%100!=0) || (year%400==0);
}
int main(){
int time1,y1,m1,d1;
int time2,y2,m2,d2;
while(scanf("%d%d",&time1,&time2)!=EOF){
if(time1>time2){ //第一个日期晚于第二个日期,则交换
int temp=time1;
time1=time2;
time2=temp;
}
y1=time1/10000,m1=time1%10000/100,d1=time1%100;
y2=time2/10000,m2=time2%10000/100,d2=time2%100;
int ans=1; //记录结果
//第一个日期没有达到第二个日期时进行循环
while(y1<y2||m1<m2||d1<d2){
d1++;
if(d1==month[m1][isLeap(y1)]+1){ //满当月天数
m1++;
d1=1;
}
if(m1==13){ //月份满12个月
y1++;
m1=1;
}
ans++;
}
printf("%d\n",ans);
}
return 0;
}
//PAT B1009 说反话 P97
#include<stdio.h>
int main(){
int num=0; //单词的个数
char ans[90][90];
while(scanf("%s",ans[num])!=EOF){ //一直输入直到文件末尾
num++; //单词个数加1
}
for(int i=num-1;i>=0;i--){ //倒着输出单词
printf("%s",ans[i]);
if(i>0) printf(" ");
}
return 0;
}
#include<iostream>
#include<string>
using namespace std;
int main(){
string str;
getline(cin,str,'\n');
// char (*ans)[90]=(char(*)[90])malloc(sizeof(char)*90*90);
// cin>>str;
int len=str.length(),r=0,h=0; //r为行,h为列
char ans[90][90]={}; //ans[0]~ans[r]存放单词
for(int i=0;i<len;i++){
if(str[i]!=' '){
ans[r][h++]=str[i];
}else{
ans[r][h]='\0';
r++;
h=0;
}
}
for(int i=r;i>=0;i--){
cout<<ans[i];
if(i>0) printf(" ");
}
return 0;
}
//PAT A1025 Ranking P103
#include<stdio.h>
#include<algorithm>
using namespace std;
struct Student{
char id[15]; //准考证号
int score;
int location_number; //考场号
int local_rank; //考场内排名
}stu[30010];
bool cmp(Student a,Student b){
if(a.score!=b.score) return a.score>b.score;
else return strcmp(a.id,b.id)<0;
}
int main(){
int n,k,num=0; //num为总考生数
scanf("%d",&n); //n为考场数
for(int i=1;i<=n;i++){
scanf("%d",&k); //该考场内人数
for(int j=0;j<k;j++){
scanf("%s%d",stu[num].id,&stu[num].score);
stu[num].location_number=i;
num++;
}
sort(stu+num-k,stu+num,cmp); //将该考场的考生排序
stu[num-k].local_rank=1;
for(int j=num-k+1;j<num;j++){
if(stu[j].score==stu[j-1].score){
stu[j].local_rank=stu[j-1].local_rank;
}else{
stu[j].local_rank=j-num+k+1;
}
}
}
printf("%d\n",num); //输出总考生数
sort(stu,stu+num,cmp); //将所有考生排序
int r=1;
for(int i=0;i<num;i++){
if(i>0 && stu[i].score!=stu[i-1].score){
r=i+1; //当前考生与上一个考生分数不同时,让r更新为人数+1
}
printf("%s %d %d %d\n",stu[i].id,r,stu[i].location_number,stu[i].local_rank);
}
return 0;
}
//输出1~3的全排列
#include<stdio.h>
const int maxn=11;
//P为当前排列,hashTable记录整数x是否已经在P中
int n,P[maxn],hashTable[maxn]={false};
//当前处理排列的第index号位
void generateP(int index){
if(index==n+1){ //递归边界,已经处理完排列的1~n位
for(int i=1;i<=n;i++){
printf("%d ",P[i]); //输出当前排列
}
printf("\n");
return;
}
for(int x=1;x<=n;x++){ //枚举1~n,试图将x填入P[index]
if(hashTable[x]==false){ //如果x不在P[0]~P[index-1]中
P[index]=x; //令P的第index位为x,即把x加入当前排列
hashTable[x]=true; //记x已在P中
generateP(index+1); //处理排列的第index+1号位
hashTable[x]=false; //已处理完P[index]为x的子问题,还原状态
}
}
}
int main(){
n=3; //欲输出1~3的全排列
generateP(1); //从P[1]开始填
return 0;
}
//区间贪心 P122
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=110;
struct Inteval{
int x,y; //开区间左右端点
}I[maxn];
bool cmp(Inteval a,Inteval b){
if(a.x!=b.x) return a.x>b.x; //先按左端点从大到小排序
else return a.y<b.y; //左端点相同的按右端点从小到大排序
}
int main(){
int n;
while(scanf("%d",&n),n!=0){
for(int i=0;i<n;i++){
scanf("%d%d",&I[i].x,&I[i].y);
}
sort(I,I+n,cmp); //把区间排序
int ans=1,lastX=I[0].x;
for(int i=1;i<n;i++){
if(I[i].y<=lastX){
lastX=I[i].x;
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
//PAT B1040/A1093 有几个PAT P147
#include<stdio.h>
#include<string.h>
const int MAXN=10010;
const int MOD=1000000007;
char str[MAXN];
int leftNumP[MAXN]={}; //每一位左边(含)P的个数
int main(){
gets(str);
int len=strlen(str);
for(int i=0;i<len;i++){
if(i>0) leftNumP[i]=leftNumP[i-1];
if(str[i]=='P') leftNumP[i]++;
}
int ans=0,rightNumT=0; //ans为答案,rightNumT记录右边T的个数
for(int i=len-1;i>=0;i--){
if(str[i]=='T') rightNumT++;
else if(str[i]=='A') ans=(ans+leftNumP[i]*rightNumT)%MOD;
}
printf("%d\n",ans);
return 0;
}
//PAT A1020 Tree Traversals P296
#include<stdio.h>
#include<queue>
using namespace std;
const int maxn=50;
struct node{
int data;
node* lchild;
node* rchild;
};
int in[maxn],post[maxn]; //中序、后序
int n; //结点个数
//返回构建出的二叉树的根结点地址
node* create(int postL,int postR,int inL,int inR){
if(postL>postR) return NULL;
node* root=new node;
root->data=post[postR];
int k;
for(k=inL;k<=inR;k++){
if(in[k]==post[postR]) break;
}
int numLeft=k-inL;
root->lchild=create(postL,postL+numLeft-1,inL,k-1);
root->rchild=create(postL+numLeft,postR-1,k+1,inR);
return root;
}
int num=0; //已输出的结点个数
void BFS(node* root){
queue<node*> q;
q.push(root);
while(!q.empty()){
node* now=q.front();
q.pop();
printf("%d",now->data);
num++;
if(num<n) printf(" ");
if(now->lchild != NULL) q.push(now->lchild);
if(now->rchild != NULL) q.push(now->rchild);
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&post[i]);
}
for(int i=0;i<n;i++){
scanf("%d",&in[i]);
}
node* root=create(0,n-1,0,n-1); //建树
BFS(root); //层序遍历
return 0;
}
//PAT A1034 Head of a Gang P354
#include<iostream>
#include<map>
#include<string>
using namespace std;
const int maxn=2010; //总人数
map<int,string> inToString; //编号->姓名
map<string,int> stringToInt; //姓名->编号
map<string,int> Gang; //head->人数
int G[maxn][maxn]={0}, weight[maxn]={0}; //邻接矩阵G、点权 weight
int n,k,numPerson=0; //边数n、下限k、总人数numPerson
bool vis[maxn]={false}; //标记是否被访问
//DFS函数访问单个连通块,nowVisit为当前访问的编号
//head为头目,numMember为成员编号,totalValue为连通块的总边权
void DFS(int nowVisit,int &head,int &numMember,int &totalValue){
numMember++; //成员人数加1
vis[nowVisit]=true; //标记nowVisit已访问
if(weight[nowVisit]>weight[head]){
head=nowVisit; //更新头目
}
for(int i=0;i<numPerson;i++){ //枚举所有人
if(G[nowVisit][i]>0){
totalValue+=G[nowVisit][i];
G[nowVisit][i]=0;
G[i][nowVisit]=0;
if(vis[i]==false){
DFS(i,head,numMember,totalValue);
}
}
}
}
//DFSTrave函数遍历整张图,获取每个连通块的信息
void DFSTrave(){
for(int i=0;i<numPerson;i++){
if(vis[i]==false){
int head=i,numMember=0,totalValue=0; //头目,成员数,总边权
DFS(i,head,numMember,totalValue);
if(numMember>2 && totalValue>k){
Gang[inToString[head]] = numMember;
}
}
}
}
//change 函数返回姓名str对应的编号
int change(string str){
if(stringToInt.find(str) != stringToInt.end()) return stringToInt[str];
else{
stringToInt[str]=numPerson;
inToString[numPerson]=str;
return numPerson++;
}
}
int main(){
int w;
string str1,str2;
cin >> n >> k;
for(int i=0;i<n;i++){
cin >> str1 >>str2 >> w;
int id1=change(str1);
int id2=change(str2);
weight[id1]+=w;
weight[id2]+=w;
G[id1][id2]+=w;
G[id2][id1]+=w;
}
DFSTrave(); //遍历整个图的所有连通块,获取Gang的信息
cout << Gang.size() << endl;
map<string,int>::iterator it;
for(it=Gang.begin();it!=Gang.end();it++){
cout << it->first << " " << it->second << endl;
}
return 0;
}
//PAT A1076 Forwards on Weibo
#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1010;
struct Node{
int id;
int layer;
};
vector<Node> Adj[maxn]; //邻接表
bool inq[maxn]={false}; //顶点是否已被加入过队列
int BFS(int s,int L){ //start为起始结点,L为层数上限
int numForward=0; //转发数
queue<Node> q;
Node start;
start.id=s;
start.layer=0;
q.push(start);
inq[start.id]=true;
while(!q.empty()){
Node topNode=q.front();
q.pop();
int u=topNode.id;
for(int i=0;i<Adj[u].size();i++){
Node next=Adj[u][i];
next.layer=topNode.layer+1;
if(inq[next.id]==false && next.layer<=L){
q.push(next);
numForward++;
inq[next.id]=true;
}
}
}
return numForward;
}
int main(){
Node user;
int n,L,numFollow,idFollow;
scanf("%d%d",&n,&L); //结点个数,层数上限
for(int i=1;i<=n;i++){
user.id=i;
scanf("%d",&numFollow);
for(int j=0;j<numFollow;j++){
scanf("%d",&idFollow);
Adj[idFollow].push_back(user); //边idFollow->i
}
}
int numQuery,s;
scanf("%d",&numQuery); //查询个数
for(int i=0;i<numQuery;i++){
memset(inq,false,sizeof(inq)); //inq数组初始化
scanf("%d",&s); //起始结点编号
int numForward = BFS(s,L);
printf("%d\n",numForward);
}
return 0;
}
//PAT A1030 Travel Plan P385
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=510;
const int INF=1000000000;
int n,m,st,ed,G[maxn][maxn],cost[maxn][maxn];
int d[maxn],c[maxn],pre[maxn];
bool vis[maxn]={false};
void Dijkstra(int s){
fill(d,d+maxn,INF);
fill(c,c+maxn,INF);
for(int i=0;i<n;i++) pre[i]=i;
d[s]=0;
c[s]=0;
for(int i=0;i<n;i++){ //循环n次
int u=-1,MIN=INF;
for(int j=0;j<n;j++){ //找到未访问的顶点中d[]最小的
if(vis[j]==false && d[j]<MIN){
u=j;
MIN=d[j];
}
}
//找不到小于INF的d[u],说明剩下的顶点和起点不连通
if(u==-1) return;
vis[u]=true;
for(int v=0;v<n;v++){
if(vis[v]==false && G[u][v]!=INF){
if(d[u]+G[u][v]<d[v]){
d[v]=d[u]+G[u][v];
c[v]=c[u]+cost[u][v];
pre[v]=u;
}else if(d[u]+G[u][v]==d[v]){
if(c[u]+cost[u][v]<c[v]){
c[v]=c[u]+cost[u][v];
pre[v]=u;
}
}
}
}
}
}
void DFS(int v){
if(v==st){
printf("%d ",v);
return;
}
DFS(pre[v]);
printf("%d ",v);
}
int main(){
scanf("%d%d%d%d",&n,&m,&st,&ed);
int u,v;
fill(G[0],G[0]+maxn*maxn,INF);
for(int i=0;i<m;i++){
scanf("%d%d",&u,&v);
scanf("%d%d",&G[u][v],&cost[u][v]);
G[v][u]=G[u][v];
cost[v][u]=cost[u][v];
}
Dijkstra(st);
DFS(ed);
printf("%d %d\n",d[ed],c[ed]);
return 0;
}
动态规划
//斐波那契数列 P425
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=1010;
int dp[maxn];
int F(int n){
if(n==0 || n==1) return 1;
if(dp[n]!=-1) return dp[n];
else{
dp[n]=F(n-1)+F(n-2);
return dp[n];
}
}
int main(){
fill(dp,dp+maxn,-1);
int n;
scanf("%d",&n);
printf("%d",F(n));
return 0;
}
//数塔问题 P426
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=1010;
int dp[maxn][maxn],f[maxn][maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
scanf("%d",&f[i][j]); //输入数塔
}
}
//边界
for(int j=1;j<=n;j++){
dp[n][j]=f[n][j];
}
//从第n-1层不断向上计算出dp[i][j]
for(int i=n-1;i>=1;i--){
for(int j=1;j<=i;j++){
//状态转移方程
dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j];
}
}
printf("%d",dp[1][1]);
return 0;
}
//最大连续子序列和 P429
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=10010;
int dp[maxn],A[maxn]; //A[i]存放序列,dp[i]存放A[i]结尾的连续序列的最大和
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){ //读入序列
scanf("%d",&A[i]);
}
//边界
dp[0]=A[0];
for(int i=1;i<n;i++){
//状态转移方程
dp[i]=max(dp[i-1]+A[i],A[i]);
}
int k=0;
for(int i=1;i<n;i++){
if(dp[i]>dp[k]){
k=i;
}
}
printf("%d\n",dp[k]);
return 0;
}
//A1007 Maximum Subsequence Sum PP387
#include<stdio.h>
const int maxn=10010;
int dp[maxn],A[maxn]; //A[i]存放序列,dp[i]存放A[i]结尾的连续序列的最大和
int s[maxn]={0}; //s[i]表示产生dp[i]的连续序列从A的哪一个元素开始
int main(){
int n;
bool flag=false; //false表示数组A中全小于0
scanf("%d",&n);
for(int i=0;i<n;i++){ //读入序列
scanf("%d",&A[i]);
if(A[i]>=0) flag=true;
}
if(flag==false){
printf("0 %d %d",A[0],A[n-1]);
return 0;
}
//边界
dp[0]=A[0];
for(int i=1;i<n;i++){
//状态转移方程
if(dp[i-1]+A[i] >= A[i]){
dp[i]=dp[i-1]+A[i];
s[i]=s[i-1];
}else{
dp[i]=A[i];
s[i]=i;
}
}
int k=0;
for(int i=1;i<n;i++){
if(dp[i]>dp[k]){
k=i;
}
}
printf("%d %d %d\n",dp[k],A[s[k]],A[k]);
return 0;
}
//最长不下降子序列(LIS) P432
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=100;
int A[N],dp[N];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&A[i]);
}
int ans=-1;
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(A[j]<=A[i] && dp[j]+1>dp[i]){
dp[i]=dp[j]+1;
}
}
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
return 0;
}
//A1045 Favorite Color Stripe PP390
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxc=210; //最大颜色数
const int maxn=10010; //最大L
int HashTable[maxc]; //将喜欢的颜色序列映射为递增序列,不喜欢的映射为-1
int A[maxn],dp[maxn];
int main(){
int n,m,x;
scanf("%d%d",&n,&m);
fill(HashTable,HashTable+maxc,-1);
for(int i=0;i<m;i++){
scanf("%d",&x);
HashTable[x]=i;
}
int L,num=0;
scanf("%d",&L);
for(int i=0;i<L;i++){
scanf("%d",&x);
if(HashTable[x]>=0){
A[num++]=HashTable[x];
}
}
int ans=-1;
for(int i=0;i<num;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(A[j]<=A[i] && dp[i]<dp[j]+1){
dp[i]=dp[j]+1;
}
}
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
return 0;
}
//6
//5 2 3 1 5 6
//12 2 2 4 1 5 5 6 3 1 1 5 6
7
//最长公共子序列(LCS) P434
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=100;
char A[N],B[N];
int dp[N][N];
int main(){
gets(A+1); //从下标为1开始读入
gets(B+1);
int lenA=strlen(A+1);
int lenB=strlen(B+1);
//边界
for(int i=0;i<=lenA;i++){
dp[i][0]=0;
}
for(int j=0;j<=lenB;j++){
dp[0][j]=0;
}
//状态转移方程
for(int i=1;i<=lenA;i++){
for(int j=1;j<=lenB;j++){
if(A[i]==B[j]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
printf("%d\n",dp[lenA][lenB]);
return 0;
}
//sadstory
//adminisorry
6
//A1045 Favorite Color Stripe PP392
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxc=210; //最大颜色数
const int maxn=10010; //最大L
int A[maxc],B[maxn],dp[maxc][maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d",&A[i]);
}
int L;
scanf("%d",&L);
for(int i=1;i<=L;i++){
scanf("%d",&B[i]);
}
//边界
for(int i=0;i<=m;i++){
dp[i][0]=0;
}
for(int j=0;j<=L;j++){
dp[0][j]=0;
}
//状态转移方程
for(int i=1;i<=m;i++){
for(int j=1;j<=L;j++){
int MAX=max(dp[i-1][j],dp[i][j-1]);
if(A[i]==B[j]){
dp[i][j]=MAX+1;
}else{
dp[i][j]=MAX;
}
}
}
printf("%d\n",dp[m][L]);
return 0;
}
//6
//5 2 3 1 5 6
//12 2 2 4 1 5 5 6 3 1 1 5 6
7
//A1040 Longest Symmetric String(最长回文子串) P394
#include<stdio.h>
#include<string.h>
const int maxn=1010;
char S[maxn];
int dp[maxn][maxn];
int main(){
gets(S);
int len=strlen(S),ans=1; //ans为最长回文子串的长度
memset(dp,0,sizeof(dp));
//边界
for(int i=0;i<len;i++){
dp[i][i]=1;
if(i<len-1){
if(S[i]==S[i+1]){
dp[i][i+1]=1;
ans=2;
}
}
}
//状态转移方程
for(int L=3;L<=len;L++){ //枚举子串的长度
for(int i=0;i+L-1<len;i++){ //枚举子串的起始端点
int j=i+L-1; //子串的右端点
if(S[i]==S[j] && dp[i+1][j-1]==1){
dp[i][j]=1;
ans=L;
}
}
}
printf("%d\n",ans);
return 0;
}
//Is PAT&TAP symmetric?
11
//A1068 Find More Coins(背包问题) PP396
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=10010;
const int maxv=110;
int w[maxn],dp[maxv];
int choice[maxn][maxv];
int flag[maxn];
bool cmp(int a,int b){
return a>b;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
sort(w+1,w+n+1,cmp); //逆序排列
//边界
for(int i=0;i<=m;i++){
dp[i]=0;
}
//状态转移方程
for(int i=1;i<=n;i++){
for(int v=m;v>=w[i];v--){
if(dp[v]<=dp[v-w[i]]+w[i]){
dp[v]=dp[v-w[i]]+w[i];
choice[i][v]=1; //放入第i件物品
}else{
choice[i][v]=0; //不放第i件物品
}
}
}
if(dp[m]!=m){
printf("No Solution"); //无解
}else{
//记录最优路径
int k=n,v=m,num=0;
while(k>=0){
if(choice[k][v]==1){
flag[k]=1;
v-=w[k];
num++;
}else{
flag[k]=0;
}
k--;
}
//输出方案
for(int i=n;i>=1;i--){
if(flag[i]==1){
printf("%d",w[i]);
num--;
if(num>0) printf(" ");
}
}
}
return 0;
}